简体   繁体   中英

NSProgress fractionCompleted key-value observing method not called

I'm trying to track the progress of my HTTP request using AFNetworking and NSProgress. Basically, my request is a multi-part form data which contains text parameters, and image data, all in one block.

This is my code for the upload task, and it seems pretty simple and normal to me:

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];

Now, what I don't understand is that the callback observer method isn't getting called even though the upload task completes and succeeds. Can someone help me understand why? Here's my code.

- (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);
    }
}

UPDATE: I followed AFNetworking's code for the uploadTaskWithStreamedRequest:... method and found that they are actually replacing my NSProgress object from inside uploadTaskWithTask:... . Naturally, if the NSProgress pointer is made to point at a new instance, that new instance is not registered for observing the fractionCompleted property. How can I do key-value observing on this new NSProgress instance without modifying the AFNetworking code directly?

Well all you need to do is move your observer to after upload task has been created and it is going to work like a charm.

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];

I abandoned this method of keeping track of the progress from an AFURLSessionManager . Instead, I used a good old 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];

You may be running into this issue, https://github.com/AFNetworking/AFNetworking/issues/1398 , which is actually due to a design limitation in NSURLSession. Towards the end of the discussion, you'll see a proposed workaround. I'm using this workaround and observing "fractionCompleted" works fine for me.

-brian

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM