Lê Khánh Vinh Lê Khánh Vinh - 4 months ago 34
Objective-C Question

IOS objective C write function with completionBlock

Hi I'm writing a

function
to call and API and get the
response
then store to
coredata
entity (Using magical record). My method simple take no input and return nothing (only call api and store data to
entity
. My purpose is to execute completionBlock code when
success
and log an
error
(so that can call the function in a
viewController
. I'm still don't know how to write it properly. Anyhelp is much appreciate.

My Apiclient

typedef void (^ApiClientSuccess)(id responseObject);
typedef void (^ApiClientFailure)(NSError *error);

- (void)getSingpostContentsOnSuccess:(ApiClientSuccess)success onFailure:(ApiClientFailure)failure {

NSString *urlString = [NSString stringWithFormat:@"%@singpost-contents.php",CMS_BASE_URL];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:GET_METHOD URLString:urlString parameters:nil error:nil];

[self sendJSONRequest:request success:^(NSURLResponse *response, id responseObject) {
success(responseObject);
} failure:^(NSError *error) {
failure(error);
[self reportAPIIssueURL:[request.URL absoluteString] payload:nil message:[error description]];
}];
}


My function (need to write it properly) so that I can call and write some code when function complete execute

+ (void)API_SingPostContentOnCompletion:(void)completionBlock {

[[ApiClient sharedInstance] getSingpostContentsOnSuccess:^(id responseJSON) {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_rootSavingContext];
[responseJSON[@"root"] enumerateObjectsUsingBlock:^(id attributes, NSUInteger idx, BOOL *stop) {
Content *content = [Content MR_findFirstOrCreateByAttribute:@"name" withValue:attributes[@"Name"] inContext:localContext];
content.content = attributes[@"content"];
}];

[localContext MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError * _Nullable error) {
if (error) NSLog(@"Error save content to persistentStore");

}];

// if (completionBlock) {
// dispatch_async(dispatch_get_main_queue(), ^{
// completionBlock();
// });
// }
});
} onFailure:^(NSError *error) {
// if (completionBlock) {
// dispatch_async(dispatch_get_main_queue(), ^{
// completionBlock(nil);
// });
// }
NSLog(@"Failed to get SingPost Content");
}];

}

Answer

Declare the blocks :

  typedef void (^ SuccessBlock)(BOOL success, id response);
  typedef void (^ FailureBlock)(NSError *error, NSInteger statusCode);

Write the method that use these blocks, for example for a simple AFNetworking POST call:

+ (void)myFunction:(NSString*)function  success:(SuccessBlock)success failure:(FailureBlock)failure{

   AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        ....
   [manager POST:functionURL parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (operation.response.statusCode == 201 || operation.response.statusCode == 200) {
                success(YES,responseObject);
            }else{
                 success(NO,responseObject);
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            failure(error, operation.response.statusCode);
        }];
  } 

and you can call your method from other class:

[YourClass myFunction:@""  success:^(BOOL success, id response) {
       if(success){
            //my call is success
       }
    } failure:^(NSError *error, NSInteger statusCode) {

    }];