Allen
Allen

Reputation: 3771

Returning on completion of a block?

Given the following code:

+(Tag *) addNewTagwithName:(NSString *)tagName Error:(NSError **)addError {
    AppDelegate *delegate = (AppDelegate *) [[UIApplication sharedApplication]delegate];

    Tag *newTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:delegate.managedObjectContext];
    newTag.tagName = tagName;

    //no error save to parse
    PFObject *tag = [PFObject objectWithClassName:@"Tag"];
    tag[@"tagName"] = newTag.tagName;

    [tag saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if(error) {
            *addError = error;
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSError *error = nil;
                newTag.tagId = tag.objectId;

                if(![delegate.managedObjectContext save:&error]) {
                    *addError = error;
                }

            });

        }
    }];

    return newTag;

}

what are some methods to ensure that newTag is returned only AFTER newTag.tagId = tag.objectId is executed?

Upvotes: 0

Views: 165

Answers (2)

Mani
Mani

Reputation: 17585

It's not possible. Because addNewTagwithName: method immediately gets return but completion block will execute later and it doesn't nothing.

Updated: Try below code...

+(void) addNewTagwithName:(NSString *)tagName Error:(NSError **)addError completionBlock:(CompletionBlock)comBlock {

    //no error save to parse
    PFObject *tag = [PFObject objectWithClassName:@"Tag"];
    tag[@"tagName"] = tagName;

    [tag saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if(error) {
            *addError = error;
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                comBlock(succeeded,error);
                if(![delegate.managedObjectContext save:&error]) {
                    *addError = error;
                }
            });
        }
    }];
}

and your method call should be.

CompletionBlock currentTagBlock = ^(BOOL succeeded, NSError *error){
      AppDelegate *delegate = (AppDelegate *) [[UIApplication sharedApplication]delegate];

      Tag *newTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:delegate.managedObjectContext];
    newTag.tagName = tagName;
      if(!error);
         newTag.tagId = tag.objectId;
      /* Here you should write your code using tag
        ex: [self processWithNewTag:newTag]; */

};
[Tag addNewTagwithName:tagName Error:&addError completionBlock:currentTagBlock];

Upvotes: 1

Puneet Sharma
Puneet Sharma

Reputation: 9484

You have used GCD asynchronously and it means the block of tasks you have provided in dispatch_async function will be spawned on another thread and thus you do not have control when it would be completed and return.

But you can return to newTag object asynchronously by accessing the main thread from the spawned thread, after you successfully save object in core data. For that you have to read more about GCD. It is always better to start from reading official docs.

Upvotes: 0

Related Questions