NSProgress fractionCompleted键值观察方法未调用

Mat*_*ros 9 iphone cocoa-touch objective-c ipad ios

我正在尝试使用AFNetworking和NSProgress跟踪我的HTTP请求的进度.基本上,我的请求是一个包含文本参数和图像数据的多部分表单数据,所有这些都在一个块中.

这是我上传任务的代码,对我来说似乎很简单和正常:

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"<THE_API_URL>" parameters:nil constructingBodyWithBlock:constructionBlock];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];

NSProgress *progress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        // UI reacts to error
    } else {
        // Do stuff here
    }
}];
[uploadTask resume];
Run Code Online (Sandbox Code Playgroud)

现在,我不明白的是,即使上传任务完成并成功,也不会调用回调观察者方法.有人可以帮我理解为什么吗?这是我的代码.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

    if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
        NSProgress *progress = (NSProgress *)object;
        NSLog(@"Progress is: %f", progress.fractionCompleted);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我遵循AFNetworking的uploadTaskWithStreamedRequest:...方法代码,发现它们实际上是NSProgress从内部替换我的对象uploadTaskWithTask:....当然,如果NSProgress指针指向新实例,则不会注册该新实例以观察该fractionCompleted属性.如何在NSProgress不修改AFNetworking代码的情况下对此新实例进行键值观察?

Yas*_* T. 7

所有你需要做的就是将你的观察者移动到创建上传任务之后,它将像魅力一样工作.

NSProgress *progress;

NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        // UI reacts to error
    } else {
        // Do stuff here
    }
}];
[uploadTask resume];

[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];
Run Code Online (Sandbox Code Playgroud)


Mat*_*ros 5

我放弃了这种跟踪进度的方法AFURLSessionManager.相反,我用了一个好老AFHTTPRequestOperation.

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"THE_API_URL" parameters:nil constructingBodyWithBlock:constructionBlock];

AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperationManager manager] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
    // Do stuff here
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // Catch error
}];
[requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
    double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    progressBlock(percentDone);
}];
[requestOperation start];
Run Code Online (Sandbox Code Playgroud)