Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios AFNetworking 3.0在应用程序移动到后台时继续上载_Ios_Swift_Afnetworking_Afnetworking 3 - Fatal编程技术网

Ios AFNetworking 3.0在应用程序移动到后台时继续上载

Ios AFNetworking 3.0在应用程序移动到后台时继续上载,ios,swift,afnetworking,afnetworking-3,Ios,Swift,Afnetworking,Afnetworking 3,我的应用程序在前台启动向服务器上传内容。由于这个过程可能需要一些时间,用户可以很好地将应用程序转换到后台 我正在使用AFHTTPSessionManager提交上传: let sessionManager = AFHTTPSessionManager() sessionManager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-type") session

我的应用程序在前台启动向服务器上传内容。由于这个过程可能需要一些时间,用户可以很好地将应用程序转换到后台

我正在使用AFHTTPSessionManager提交上传:

let sessionManager = AFHTTPSessionManager()
sessionManager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-type")
sessionManager.POST(urlStr, parameters: params, constructingBodyWithBlock: { (formData) -> Void in
    formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
}, progress: { (progress) -> Void in
}, success: { (task, responseObject) -> Void in
    print(responseObject)
    success(responseObject: responseObject)
}, failure: { (task, error) -> Void in
    print(error)
    if let errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData {
        do {
            let json = try NSJSONSerialization.JSONObjectWithData(errorData, options: NSJSONReadingOptions.MutableContainers)
            failure(error: error, responseObject: json)
        } catch let error {
            print(error)
        }
    }
})
我需要在应用程序处于后台状态时继续此过程,直到完成。有一个很好的答案让我走上了正确的道路,但在某些地方我仍然一无所知。我尝试使用链接答案中的“BackgroundSessionManager”类将我的上传呼叫更改为:

BackgroundSessionManager.sharedManager().POST(NetworkManager.kBaseURLString + "fulfill_request", parameters: params, constructingBodyWithBlock: { (formData) -> Void in
    formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
}, progress: nil, success: nil, failure: nil)?.resume()
并将此添加到我的AppDelegate:

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
    BackgroundSessionManager.sharedManager().savedCompletionHandler = completionHandler
}

但是我在一些后台线程上遇到了EXC_BAD_访问崩溃,几乎没有信息。我是否正确地处理了这个问题?

一些观察结果:

  • 您正在生成一个多部分请求,但随后强制将
    内容类型
    标题设置为
    应用程序/x-www-form-urlencoded
    。但这不是多部分请求的有效内容头。我建议删除请求头的手动配置(或者告诉我们为什么这样做)。AFNetworking将为您设置
    内容类型

  • 您可能只想请求一点时间来完成请求,即使在用户离开应用程序之后,您也不必为后台会话而烦恼

    var backgroundTask = UIBackgroundTaskInvalid
    
    func uploadImageWithData(dataObject: NSData, mimeType: String, urlStr: String, params: [String: String]?, success: (responseObject: AnyObject?) -> (), failure: (error: NSError, responseObject: AnyObject) -> ()) {
        let app = UIApplication.sharedApplication()
    
        let endBackgroundTask = {
            if self.backgroundTask != UIBackgroundTaskInvalid {
                app.endBackgroundTask(self.backgroundTask)
                self.backgroundTask = UIBackgroundTaskInvalid
            }
        }
    
        backgroundTask = app.beginBackgroundTaskWithName("com.domain.app.imageupload") {
            // if you need to do any addition cleanup because request didn't finish in time, do that here
    
            // then end the background task (so iOS doesn't summarily terminate your app
            endBackgroundTask()
        }
    
        let sessionManager = AFHTTPSessionManager()
        sessionManager.POST(urlStr, parameters: params, constructingBodyWithBlock: { (formData) -> Void in
            formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
            }, progress: { (progress) -> Void in
            }, success: { (task, responseObject) -> Void in
                print(responseObject)
                success(responseObject: responseObject)
                endBackgroundTask()
            }, failure: { (task, error) -> Void in
                print(error)
                if let errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData {
                    do {
                        let json = try NSJSONSerialization.JSONObjectWithData(errorData, options: NSJSONReadingOptions.MutableContainers)
                        failure(error: error, responseObject: json)
                    } catch let error {
                        print(error)
                    }
                }
                endBackgroundTask()
        })
    }
    
  • 我建议添加一个,看看这是否有助于追踪违规线路

    坦率地说,如果异常在
    NSURLSession
    内部处理中异步发生,这可能没有帮助,但这是我在试图追踪异常源时首先尝试的

  • 如果您确实觉得必须使用后台会话(即,您的上载任务可能需要超过
    beginBackgroundTaskWithName
    允许的三分钟),请注意后台任务必须是上载或下载任务

    但是,我相信
    POST
    方法将创建一个数据任务。在iOS 7中,根本不允许在后台会话中使用数据任务。在iOS 8中,您可以使用后台任务启动数据任务,但您必须使用
    NSURLSessionResponseBecomeDownload
    响应
    didReceiverResponse
    ,例如,在
    BackgroundSessionManager
    configureDownloadFinished
    中,您可以尝试添加:

    [self setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response) {
        return NSURLSessionResponseBecomeDownload;
    }];
    
  • 或者,如果必须再次使用后台会话,则可能需要手动构建
    NSURLRequest
    对象,并将其作为上载或下载任务提交,而不是使用
    POST
    。AFNetworking提供了将请求的构建和请求的提交解耦的机制,因此如果您需要沿着这条路走下去,请告诉我们,我们可以向您展示如何做到这一点


  • 总之,
    beginBackgroundTaskWithName
    比使用background
    NSURLSession
    更容易请求一点时间来完成请求。只有在绝对必要的情况下(例如,您很有可能需要三分钟以上才能完成请求),才可以执行后一种操作。

    非常感谢您如此彻底。我会尝试你提出的一些不同的建议,并发布一个更新。只是出于好奇,对于简单的背景任务,你的3分钟时间限制在哪里?苹果似乎对实际的时间限制非常模糊,但我在其他地方看到它可以支持10分钟。据我所知,任何地方都没有正式的文档记录,尽管我模糊地记得它在一个WWDC视频中被引用过。过去是10分钟,但现在是3分钟。如果你打电话,它会准确地告诉你有多少时间。再次感谢。最后使用了名为的BeginBackgroundTask。我们可能希望在将来使用后台会话,但更简单的方法效果很好。@Rob上传任务需要3分钟以上怎么办?我想上传视频到服务器的参数和使用AFNetworking。使用post、上传任务和数据任务方法。但系统只提供3分钟的上传时间。在此之后,应用程序将终止并停止上传。