【问题标题】:Not sure what happens to my apps objects when using NSURLSession in background - what state is my app in?不确定在后台使用 NSURLSession 时我的应用程序对象会发生什么 - 我的应用程序处于什么状态?
【发布时间】:2014-08-21 15:30:17
【问题描述】:

更多一般性问题 - 在“background session mode”中使用NSURLSession 时,我不明白它的工作原理。我将提供一些简单的人为示例代码。

我有一个保存对象的数据库 - 这样部分数据可以上传到远程服务器。重要的是要知道上传了哪些数据/对象,以便准确地向用户显示信息。能够在后台任务中上传到服务器也很重要,因为应用程序可以随时终止。

例如一个简单的头像对象:

@interface ProfilePicture : NSObject

@property int userId;
@property UIImage *profilePicture;
@property BOOL successfullyUploaded; // we want to know if the image was uploaded to out server - this could also be a property that is queryable but lets assume this is attached to this object

@end

现在假设我想将个人资料图片上传到远程服务器 - 我可以执行以下操作:

@implementation ProfilePictureUploader

-(void)uploadProfilePicture:(ProfilePicture *)profilePicture completion:(void(^)(BOOL successInUploading))completion
{
     NSUrlSession *uploadImageSession = ..... // code to setup uploading the image - and calling the completion handler;
     [uploadImageSession resume];
}

@end

现在我想在我的代码中的其他地方上传个人资料图片 - 如果成功更新 UI 和发生此操作的数据库:

ProfilePicture *aNewProfilePicture = ...;
aNewProfilePicture.profilePicture = aImage;
aNewProfilePicture.userId = 123;
aNewProfilePicture.successfullyUploaded = NO;

// write the change to disk
[MyDatabase write:aNewProfilePicture];

// upload the image to the server
ProfilePictureUploader *uploader = [ProfilePictureUploader ....];
[uploader uploadProfilePicture:aNewProfilePicture completion:^(BOOL successInUploading) {
  if (successInUploading) {
    // persist the change to my db.
    aNewProfilePicture.successfullyUploaded = YES;
    [Mydase update:aNewProfilePicture]; // persist the change 
  }
}];

现在很明显,如果我的应用程序正在运行,那么这个“ProfilePicture”对象已成功上传,一切都很好 - 数据库对象有自己的数据结构/缓存内部工作,什么不是。所有可能存在的回调都得到维护,应用状态一目了然。

但我不清楚如果应用在上传过程中的某个时间点“死机”会发生什么。似乎任何回调/通知都已失效。根据 API 文档,上传由单独的进程处理。因此上传将继续,我的应用程序将在未来某个时候被唤醒以处理完成。但是对象“aNewProfilePicture”此时不存在,所有回调/对象都消失了。我不明白此时存在什么上下文。我应该如何确保我的数据库和 UI 的一致性(例如更新该用户的“successfullyUploaded”属性)?我是否需要重新处理所有与 DB 或 UI 相关的内容以与新 API 相对应并在无上下文环境中工作?

【问题讨论】:

    标签: ios nsurlsession nsurlsessionconfiguration nsurlsessionuploadtask


    【解决方案1】:

    您可以使用具有后台配置的 NSURLSession 下载和上传文件。你必须实现 NSURLSessionDelegate、NSURLSessionDownloadDelegate、NSURLSessionUploadDelegate。使用后台会话,您不能再使用完成处理程序。我发现本教程对理解后台 NSURLSession 的工作方式非常有帮助: http://www.appcoda.com/background-transfer-service-ios7/.

    在您的情况下,您可以执行以下操作:创建上传任务时,您可以将数据库中的用户 ID 分配给 NSURLSessionTask 的“taskDescription”属性。上传完成后,调用委托方法,你可以实现如下:

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
       int userID = [task.taskDescription intValue];
       [self.database updateUserRecordWithID:userID];
    }
    

    【讨论】:

    • 我明白这一点。但我的问题是关于应用程序在后台时的上下文
    • 您的应用可以处于除“未运行”之外的任何状态。一旦 nsnetwork 守护进程完成上传/下载您的文件,您的应用将被唤醒并调用委托方法。
    • 因此应用程序的任何状态都会丢失。应用如何知道它应该处于什么新状态
    • 如果您的应用程序崩溃或其他原因,上传完成后操作系统会唤醒您。在此方法中 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 您需要识别已上传的内容,然后采取适当的措施,例如更新您的数据库、用户界面等
    猜你喜欢
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多