2015-12-15 114 views
3

據我瞭解,後臺任務可以實現以執行需要比分配的3-4秒applicationDidEnterBackground你使用像這樣提供了更多的特定過程:iOS的後臺任務沒有完成

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{ 

     // Clean up your background stuff 

     NSLog(@"Finsihed background task."); 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    // Begin your background stuff... 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Do something...like update Parse DB 
     NSLog(@"Doing something..."); 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }); 
} 

不幸的是,我似乎在這裏失去一些東西。雖然我收到Doing something...這是從上面的代碼是相當明顯的,我從來沒有收到任何種類的指示後臺任務過期或曾經進入expirationHandler正確完成任務。

我很困惑,「做某事」調度如何與後臺任務相關,或者與任務相關聯,讓應用程序知道允許此過程在應用程序允許的〜10分鐘內完成BG任務。

注意:我確保我已允許在我的info.plist中使用Background Modes,因爲許多發佈的解決方案指出可能是其他人的問題。

如果有人可以幫助我正確地完成後臺任務,我會非常感激。

FYI:這樣做的主要目的是用查詢更新我的Parse數據庫,以將用戶新值(本地到設備)值設置爲數據庫。這是我會使用的情況下,我不是足夠清楚:

// Do something...like update Parse DB 
NSLog(@"Doing something..."); 
. . . 
PFQuery *query = [PFQuery queryWithClassName:@"_User"]; 
// Retrieve the object by id 
[query getObjectInBackgroundWithId:<SOME_OBJECT_ID> block:^(PFObject *userInfo, NSError *error) { 
    // Save user info to current user info on Parse 
    [userInfo saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) { 
     if (error != nil) { 
      NSLog(@"Could not update Parse with error: %@", error); 
     } 
     else { 
      NSLog(@"Updated Parse successfully."); 
     } 
    }]; 
}]; 

UPDATE: 我曾試着撥打解析塊內[application endBackgroundTask:bgTask];但它不會被調用。有幾次它假設這兩次都是最快的,但我正在嘗試處理更新Parse成功所需的時間比關閉應用程序所需的時間更長的情況。下面是我做的:

- (void)applicationDidEnterBackground:(UIApplication *)application { 
    if ([[UIDevice currentDevice] isMultitaskingSupported]) { 
     NSLog(@"Good for you."); 
    } 

    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
    self.backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId]; 
     NSLog(@"done"); 
    }]; 

    // Begin your background stuff... 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Do something...like update Parse DB 
     NSLog(@"Doing something..."); 

     PFQuery *query = [PFQuery queryWithClassName:@"_User"]; 
     // Retrieve the object by id 
     [query getObjectInBackgroundWithId:<SOME_OBJECT_ID> block:^(PFObject *userInfo, NSError *error) { 
      // Save user info to current user info on Parse 
      userInfo[@"test"] = [NSNumber numberWithInteger:12345]; 

      [userInfo saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) { 
       if (error != nil) { 
        NSLog(@"Could not update Parse with error: %@", error); 
        [application endBackgroundTask:self.backgroundTaskId]; 
        self.backgroundTaskId = UIBackgroundTaskInvalid; 
       } 
       else { 
        NSLog(@"Updated Parse successfully."); 
        [application endBackgroundTask:self.backgroundTaskId]; 
        self.backgroundTaskId = UIBackgroundTaskInvalid; 
       } 
      }]; 
     }]; 
    }); 
} 
+1

到期處理程序,如果你的後臺任務到期時纔會調用。由於在過期之前調用'endBackgroundTask',處理程序將不會被調用。我懷疑你的問題是你在後臺調度Parse活動,但接着調用'endBackgroundTask'。只有在更新完成後,才應該調用'endBackgroundTask'。 – Paulw11

+0

好吧,很高興知道。我仍然不確定如何讓'dispatch_async'正確執行任務。例如,我試圖讓它在10分鐘後爲NSLog調用一個GCD,並且它從未被解僱。 –

+0

它的工作原理很簡單'做些什麼......'但我無法完成任何需要超過應用程序終止時間的事情:\ –

回答

1

你有正確的結構一般,除非你在呼喚從[application endBackgroundTask:self.backgroundTaskId];dispatch_async塊外,所以後臺任務將會結束前的解析操作將完成。另外,如果您正在更新的用戶是當前登錄的用戶,則可以使用PFUser.currentUser而不必搜索。

所以,你應該applicationDidEnterBackground是這樣的:

- (void)applicationDidEnterBackground:(UIApplication *)application { 

    self.bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{ 

     // Clean up your background stuff 

     NSLog(@"Expired background task."); 
     [application endBackgroundTask:self.bgTask]; 
     self.bgTask = UIBackgroundTaskInvalid; 
    }]; 

    // Begin your background stuff... 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     NSLog(@"Doing something..."); 

     // Do something...like update Parse DB 
     PFUser *user=[PFUser currentUser]; 
     // Update User fields as required 
     [user saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) { 
      if (succeeded) { 
       NSLog(@"Saved user"); 
      } else { 
       NSLog(@"Error:%@",error.localizedDescription); 
      } 
      NSLog(@"Background time remaining=%f",UIApplication.sharedApplication.backgroundTimeRemaining); 
      [application endBackgroundTask:self.bgTask]; 
      self.bgTask = UIBackgroundTaskInvalid; 
     }]; 


    }); 
}