Aleem
Aleem

Reputation: 3291

How to stop call which is sent in operation queue in Objective-C

I am working on iOS App, and I am using AFNetworking for interacting with server API. My issue is I want to send call and don't want to restrict user until response get from server, so issue is crash. When user move back to that particular screen lets say I have listing screen where I am getting data which is taking 6-7 seconds and meanwhile user move back to previous screen and when data come from API and call back that delete to listing screen but user move backed to that screen then App crashes Here below is code for fetching data call.

+ (void) getRequestForDocumentListing:(NSDictionary *)headerParams urlQuery: (NSString*)action parameters:(NSDictionary*)params
                       onComplete:(void (^)(id json, id code))successBlock
                          onError:(void (^)(id error, id code))errorBlock
{
    NSString *authorizationValue = [self setAuthorizationValue:action];
    NSString *selectedLanguage = [ApplicationBaseViewController getDataFromDefaults:@"GLOBALLOCALE"];
    NSString *language = selectedLanguage;

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

//set headers values
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:language forHTTPHeaderField:@"Accept-Language"];
[manager.requestSerializer setValue:authorizationValue forHTTPHeaderField:@"authorization"];
[manager.requestSerializer setValue:@"x-folder" forHTTPHeaderField:@"inbox"];
[manager GET:action parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"document listing success");
    
    NSInteger statusCode = [operation.response statusCode];
    NSNumber *statusObject = [NSNumber numberWithInteger:statusCode];
    
    successBlock(responseObject, statusObject);
}
     failure:^(AFHTTPRequestOperation *operation, NSError *error)
 {
     NSInteger statusCode = [operation.response statusCode];
     NSNumber *statusObject = [NSNumber numberWithInteger:statusCode];
     
     id responseObject = operation.responseData;
     id json = nil;
     id errorMessage = nil;
     
     if (responseObject) {
         
         json = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:&error];
         errorMessage = [(NSDictionary*)json objectForKey:@"Message"];
     }else{
         json = [error.userInfo objectForKey:NSLocalizedDescriptionKey];
         errorMessage = json;
     }
     
     errorBlock(errorMessage, statusObject);
 }];
}

What I need is to stop call in ViewdidDisappear View delegate

- (AFHTTPRequestOperation *)GET:(NSString *)URLString
                 parameters:(id)parameters
                    success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                    failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure];
    [self.operationQueue addOperation:operation];
    
    return operation;
}

How to solve this particular issue?

Upvotes: 1

Views: 603

Answers (3)

Aleem
Aleem

Reputation: 3291

Thanks RuchiraRandana and childrenOurFuture for your answer, I got help from your answers and finally I come to solution where I am not going to cancel operation and set nil delegate, because my others operation are also in working which is trigger on other screen.

I create a just BOOL and set YES default value in singleton class and also set to no in - (void)dealloc on that particular class and in API class where I am triggering that delegate I added that check.

if ([SHAppSingleton sharedInstance].isDocListControllerPop == YES) {
         [delegate documentListResponse:documentList andStatusCode:code];
     }

I know this might not be perfect solution but this resolved my issue. Thanks

Upvotes: 0

Ruchira Randana
Ruchira Randana

Reputation: 4179

First get a reference to the Operation object by

AFHTTPRequestOperation *operation = [manager GET:action parameters:nil success:^...blah blah blah...];

Then you can set the completion block to nil when you move away from this screen.

[operation setCompletionBlock:nil];

Please note that even though you move away from the screen, the request may actually execute successfully. However, your app will not crash now.

Upvotes: 1

childrenOurFuture
childrenOurFuture

Reputation: 1987

I got your point, I think the problem is not about the AFNetWorking or download, it is about how you organize your view controllers.
In short, you need to make sure the synchronization of the data and view.
What cause your crash is when users do some operation(eg. delete, move...), the data is not the same with what view shows.

Let's play back an example:
An array with 12 objects and show it with a table view.
User call a web request to change the array. As we know, it needs time.
User leave and come back again. In this view, table view shows with the old array.
At this point, web request comes back. The array is modified to 10 object.But at this time, the call back dose not cause the table view to load the new data.
When user do some operation, just like delete the 11st object in the table view. Actually, there is no 11st object in array.
So crash comes.

How to deal with it is to keep the synchronization of the data and view.

Upvotes: 1

Related Questions