【问题标题】:Returning on completion of a block?完成一个块返回?
【发布时间】:2014-01-07 06:19:50
【问题描述】:

给定以下代码:

+(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;

}

有哪些方法可以确保只在执行 newTag.tagId = tag.objectId 之后才返回 newTag?

【问题讨论】:

标签: ios objective-c core-data objective-c-blocks


【解决方案1】:

这是不可能的。因为addNewTagwithName: 方法会立即返回,但完成块会稍后执行,它什么也不做。

更新: 试试下面的代码...

+(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;
                }
            });
        }
    }];
}

你的方法调用应该是。

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

【讨论】:

  • @Allen 你应该重新设计流程。我可以建议或更新我的答案吗?
  • @Allen 如果您是块概念的初学者,请花一些时间来理解这一点。
【解决方案2】:

您已异步使用 GCD,这意味着您在 dispatch_async 函数中提供的任务块将在另一个线程上生成,因此您无法控制它何时完成并返回。

但是您可以在成功将对象保存在核心数据中后,通过从派生线程访问主线程来异步返回 newTag 对象。 为此,您必须阅读有关 GCD 的更多信息。 从阅读official docs开始总是更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    相关资源
    最近更新 更多