NSProgress fractionCompleted key-value observing method not called

cocoa-touch, ios, ipad, iphone, objective-c

Solution

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

Problem

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?

Original source