2015-12-15 101 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; 
     }]; 


    }); 
}