ja.
ja.

Reputation: 467

Objective-C method with completion block returns value that I want to use in the completion block

I've encountered this problem several times coding for iOS with AFNetworking but I've managed to find a workaround until now.

Basically, I want to make an API call that returns an value to the main thread that I want to then use in the completion block of the call.

More specifically, I have a post object (like posting a tweet or something) that has associated #tags and @tags that I want to POST after the initial "tweet" is created in my db. I need it to be in the completion block of the method because I need to use the post_id as a parameter for posting the #tags and @tags:

-(void)postToDB
{
    _postId = [[[ReelRailsAFNClient sharedClient] createPostWithParameters:
                                                            @{@"user_id":_userId,
                                                              @"caption":_caption}
                                            CompletionBlock:^(NSError *error) {
                                                if(!error){
                                                    [self postHashtagsToDB:_postId];
                                                    [self postAttagsToDB:_postId];
                                                 }
                                            }] postId];
    }

Inside the body of postHashtagsToDB and postAttagsToDB, _postId evaluates to (null). How do I capture and inject the postId into postHashtagsToDB and postATtagsToDB?

Thanks,

JA

EDIT:

here is my method definition for createPostWithParameters:CompletionBLock:

- (Post*) createPostWithParameters:(NSDictionary*)parameters
              CompletionBlock:(AFNClientErrorCompletionBlock)block{
    Post *post = [[Post alloc] init];

    [self POST:@"posts" parameters:parameters
         success:^(NSURLSessionDataTask *task, id responseObject){
            NSLog(@"Post Created Successfully");
            post = responseObject;
            block(nil);
     }failure:^(NSURLSessionDataTask *task, NSError *error) {
            NSLog(@"Post Not Created");
            block(error);
     }];
    return post;
}

Upvotes: 1

Views: 1525

Answers (1)

Ian MacDonald
Ian MacDonald

Reputation: 14000

ReelRailsAFNClient appears to be a class you control (I literally found one result on Google -- this question). Since you control it, I suggest modifying the completion block API to supply the post ID if you expect to be able to use it within the contents of the block.

Side note: try not to name things that aren't classes with a leading uppercase character. CompletionBlock is unconventional; replace it with completionBlock or simply completion.

Edit: You may modify your API to be something like this:

typedef void (^AFNClientErrorCompletionBlock)(Post *post, NSError *error);

- (void)createPostWithParameters:(NSDictionary*)parameters
          completionBlock:(AFNClientErrorCompletionBlock)block{
  Post *post = [[Post alloc] init];

  [self POST:@"posts" parameters:parameters
     success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"Post Created Successfully");
        post = responseObject;
        block(post, nil);
   }failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"Post Not Created");
        block(post, error);
   }];
}

Side note: If you are returning an object (i.e. an instance of Post) it is a good idea to not assign it to something called _postID. A more appropriate assignment is _post.

Upvotes: 7

Related Questions