【问题标题】:AFNetworking 1.x to 3.x migration for NSURLSessionTask?NSURLSessionTask 的 AFNetworking 1.x 到 3.x 迁移?
【发布时间】:2016-05-22 00:30:08
【问题描述】:

我有一个旧项目无法在 iOS 9 中运行。我已阅读有关 AFNetworking 的官方文档并完成了大部分迁移。

网络管理器:

_requestManager = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:baseURL ]];
//here we can set the request header as the access token once we have logged in.
AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
AFHTTPResponseSerializer *responseSerializer = [AFHTTPResponseSerializer serializer];
[_requestManager setRequestSerializer:requestSerializer];
[_requestManager setResponseSerializer:responseSerializer];

早期版本:

// 2. Create an `NSMutableURLRequest`.
NSMutableURLRequest *request =
    [[NetworkManager sharedInstance].requestManager.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:fullPath
                                                                                          parameters:nil
                                                                           constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
    NSString *fileName = [NSString stringWithFormat:@"%@.caf", theAudioItem.media_item_name];
    [formData appendPartWithFileData:audioData name:theAudioItem.media_item_name fileName:fileName mimeType:@"audio/caf"];
}];

// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
AFHTTPRequestOperation *operation =
    [[NetworkManager sharedInstance].requestManager HTTPRequestOperationWithRequest:request
                                                                            success: ^(AFHTTPRequestOperation *operation, id responseObject) {
    result(YES, @"");
} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
    if (operation.responseData) {
        NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:operation.responseData options:NSJSONReadingMutableContainers error:nil];

        result(NO, [responseDict valueForKey:@"Message"]);
        [self deleteTmpFilesFromParts:formParts];
    } else {
        result(NO, [NSString stringWithFormat:@"Failed to upload media to %@!", gallery.gallery_name]);
        [self deleteTmpFilesFromParts:formParts];
    }


    result(NO, errorMessage);
}];

// 4. Set the progress block of the operation.
[operation setUploadProgressBlock: ^(NSUInteger __unused bytesWritten,
                                     long long totalBytesWritten,
                                     long long totalBytesExpectedToWrite) {
    DLog(@"progress is %i %lld %lld", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
    progress((float)totalBytesWritten / (float)totalBytesExpectedToWrite);
}];

// 5. Begin!
[operation start];

转换后的响应:(使用 cmets 更新会出现错误)

//No visible @interface for 'AFHTTPRequestSerializer<AFURLRequestSerialization>' declares the selector 'multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:'
    NSMutableURLRequest *request =
        [[NetworkManager sharedInstance].requestManager.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:fullPath parameters:nil
                                                                               constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
        NSString *fileName = [NSString stringWithFormat:@"%@.caf", theAudioItem.media_item_name];
        [formData appendPartWithFileData:audioData name:theAudioItem.media_item_name fileName:fileName mimeType:@"audio/caf"];
    }];

    // 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
   //No visible @interface for 'AFHTTPSessionManager' declares the selector 'HTTPRequestOperationWithRequest:success:failure:'
    NSURLSessionTask *operation =
        [[NetworkManager sharedInstance].requestManager HTTPRequestOperationWithRequest:request
                                                                                success: ^(NSURLSessionTask *operation, id responseObject) {
        result(YES, @"");
    } failure: ^(NSURLSessionTask *operation, NSError *error) {

        //Error for operation doesn't have responseData
        if (operation.responseData) {
            NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:operation.responseData options:NSJSONReadingMutableContainers error:nil];

            result(NO, [responseDict valueForKey:@"Message"]);
            [self deleteTmpFilesFromParts:formParts];
        } else {
            result(NO, [NSString stringWithFormat:@"Failed to upload media to %@!", gallery.gallery_name]);
            [self deleteTmpFilesFromParts:formParts];
        }

        // get the response
        result(NO, errorMessage);
    }];

    // 4. Set the progress block of the operation.
    //No visible @interface for 'NSURLSessionTask' declares the selector 'setUploadProgressBlock:'
    [operation setUploadProgressBlock: ^(NSUInteger __unused bytesWritten,
                                         long long totalBytesWritten,
                                         long long totalBytesExpectedToWrite) {
        DLog(@"progress is %i %lld %lld", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
        progress((float)totalBytesWritten / (float)totalBytesExpectedToWrite);
    }];

    // 5. Begin!
    //No visible @interface for 'NSURLSessionTask' declares the selector 'start'
    [operation start];

【问题讨论】:

    标签: objective-c ios9 xcode7 nsurlsession afnetworking-3


    【解决方案1】:

    AFHTTPSessionManager 的等效代码是:

    NSURLSessionTask *task = [[[NetworkManager sharedInstance] requestManager] POST:fullPath parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSString *fileName = [NSString stringWithFormat:@"%@.caf", theAudioItem.media_item_name];
        [formData appendPartWithFileData:audioData name:theAudioItem.media_item_name fileName:fileName mimeType:@"audio/caf"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        NSLog(@"%.3f", uploadProgress.fractionCompleted);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        // success
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        // failure
    
        // if you need to process the `NSData` associated with this error (if any), you'd do:
    
        NSData *data = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
        if (data) { ... }
    }];
    

    这与您的 v1.x 代码相比有两个主要变化:首先,他们在 2.x 中引入了GET/POST/等。使您免于手动启动操作(或将其添加到您自己的队列)的方法。其次,在 3.x 中,他们淘汰了AFHTTPRequestOperationManagerNSOperation 框架,现在使用AFHTTPSessionManager 类,其中GET/POST/等。不要返回 NSOperation 子类,而是返回 NSURLSessionTask 引用。

    【讨论】:

    • 非常感谢 Rob,但是如何在 NSURLSessionDataTask 中读取失败响应数据?
    • 如果失败,failure 块中的代码将被调用。
    • 我的意思是 NSURLSessionDataTask 中没有 task.responseData 属性。我不能将它转换成字典并使用 web 服务发送的特定键读取数据吗? (示例在我的代码 sn-p 中)
    • AFNetworkingOperationFailingURLResponseDataErrorKey 键具有与failure 块中的响应(如果有)关联的NSData。如果您出于任何原因需要NSHTTPURLResponse,则在AFNetworkingOperationFailingURLResponseErrorKey 下方。请参阅修改后的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 2023-03-29
    • 2018-08-10
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多