【问题标题】:NSURLSession: background upload and then call a service apiNSURLSession:后台上传然后调用一个服务api
【发布时间】:2014-02-11 01:29:46
【问题描述】:

我正在尝试使用新的 ios7 后台传输 api 将一些照片上传到服务器。现在发生的事情是 1)我们将字节上传到 s3 2) 调用服务 api 来“完成”上传

我查看了这个文档,似乎后台 NSURLSession 不支持“数据”任务。这是否意味着在实际上传完成后我无法在后台执行第 2 步?

【问题讨论】:

  • 你有没有得到任何答案。我有同样的问题
  • 是的。我发现我可以使用 NSURLSessionDownloadTask 进行服务调用。它与 NSURLSessionDataTask 非常相似,只是服务响应 xml/json 将存储在磁盘上...
  • 那么你的解决方案是什么?您是否在 NSURLSession:task:didCompleteWithError: 中创建了第二个 NSURLSession 任务?
  • 虽然后台 NSURLSession 不支持 dataTask,但支持下载任务。您可以使用后台 downloadTask 发送 POST 请求。看这里stackoverflow.com/questions/19700572/…
  • 另一方面,由于 POST 请求通常非常快,您可以使用前台 NSURLSession 创建一个 dataTask 来发送 POST 请求。您可以在 NSURLSession:task:didCompleteWithError 回调中执行此操作,因为该回调通常会给您 15 秒的时间来进行前台调用。

标签: ios ios7 afnetworking nsurlsession


【解决方案1】:

如果您想要一个比将 NSURLSessionDownloadTask 重新用于“已完成”API 调用更简单的解决方案,您可以在回调期间往返快速 http 调用:

-URLSession:task:didCompleteWithError:

【讨论】:

  • 你能在这里提供更多细节来解释为什么会这样吗?
【解决方案2】:

对于具有后台任务的 S3,请参阅我的回答 here

另一个很好的资源是苹果示例代码here 并寻找“简单后台传输”

您必须创建一个上传任务并从本地文件上传。当您的应用程序正在运行时,NSURLSessionTaskDelegate 委托方法将在完成时调用,特别是在上传完成时:

    /* Sent as the last message related to a specific task.  Error may be
    * nil, which implies that no error occurred and this task is complete. 
    */
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                       didCompleteWithError:(NSError *)error;

如果您的应用程序进入后台甚至被 iOS(而不是用户)杀死,您的应用程序将被唤醒

URLSessionDidFinishEventsForBackgroundURLSession

然后你的 NSURLsession 委托方法会被调用

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session

你应该构建它的方式如下,在你的appDelegate中添加

        - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
       {
           /*
            Store the completion handler. The completion handler is invoked by the view            controller's checkForAllDownloadsHavingCompleted method (if all the download tasks have been            completed).
            */
        self.backgroundSessionCompletionHandler = completionHandler;
       }

然后在你的控制器/模型类中添加

    /*
     If an application has received an -        application:handleEventsForBackgroundURLSession:completionHandler: message, the session         delegate will receive this message to indicate that all messages previously enqueued for this session have been delivered. At this time it is safe to invoke the previously stored         completion handler, or to begin any internal updates that will result in invoking the         completion handler.
     */
    - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
    {
        APLAppDelegate *appDelegate = (APLAppDelegate *)[[UIApplication sharedApplication] delegate];
        if (appDelegate.backgroundSessionCompletionHandler) {
            void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
            appDelegate.backgroundSessionCompletionHandler = nil;
            completionHandler();
        }

        NSLog(@"All tasks are finished");
    }

【讨论】:

    【解决方案3】:

    NSURLSessions 有一个委托方法URLSessionDidFinishEventsForBackgroundURLSession,它在会话完成所有任务后调用。我相信你应该在那里执行一个 api 调用。

    【讨论】:

      【解决方案4】:
      - (void)applicationDidEnterBackground:(UIApplication *)application
      {
      
      if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
      {
          NSLog(@"Multitasking Supported");
      
          __block UIBackgroundTaskIdentifier background_task;
          background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
      
              //Clean up code. Tell the system that we are done.
              [application endBackgroundTask: background_task];
              background_task = UIBackgroundTaskInvalid;
          }];
      
          //To make the code block asynchronous
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      
              //### background task starts
              NSLog(@"Running in the background\n");
              while(TRUE)
              {
                  NSLog(@"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
                  [NSThread sleepForTimeInterval:1]; //wait for 1 sec
              }
              //#### background task ends
      
              //Clean up code. Tell the system that we are done.
              [application endBackgroundTask: background_task];
              background_task = UIBackgroundTaskInvalid; 
          });
      }
      else
      {
          NSLog(@"Multitasking Not Supported");
      }
      }
      

      将此代码放入 appdelegate.m 文件中

      试试这个代码,希望对你有帮助。

      【讨论】:

      • 这在 iOS7 中效果不佳,尤其是对于需要很长时间才能完成的任务。问题是关于 NSURLSession
      猜你喜欢
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多