1

我在 viewControllers 之间使用 Blocks 而不是委托进行回调,但我无法弄清楚为什么这种情况不起作用:

所以我有一个调用detailViewController的mainViewController,当返回作为mainViewController属性的tableView时需要重新加载。

DetailViewController *actionDetail = [[DetailViewController alloc]initWithSaveBlock:^{
        [self.tableView reloadData]  //app crashes here
}];

当用户点击“保存按钮”时,在 detailViewController 中调用“保存”

- (void)save
{
    if (self.saveBlock)
        self.saveBlock();

    [self dismissModalViewControllerAnimated:YES];
}

出于某种原因,[self.tableView reloadData]不符合[self dismissModalViewControllerAnimated:YES]. 如果我删除这两个应用程序之一,应用程序似乎工作正常,显然比我错过了预期的行为。

当应用程序崩溃时,控制台中的消息是:

Previous frame inner to this frame (gdb could not unwind past this frame)

任何人都知道为什么这不起作用?

更新: SaveBlock 是这样定义的

typedef void (^SaveBlock)();

@interface DetailViewController : UIViewController
{

}
@property(nonatomic,assign)SaveBlock saveBlock;
4

2 回答 2

7

您需要将您的块属性声明为copy

@property(nonatomic, copy) SaveBlock saveBlock;

您不能使用assignstrong。原因是您需要确保拥有自己的块副本。传入的那个可能在一个堆栈帧上,当你开始运行该块时它可能已经消失了。因此,您需要触发 aBlock_copy()以确保将块复制到堆中(或者如果它已经存在则保留)。

[注意:这个解释非常简洁。如果您想完全理解它,我建议您阅读有关块运行时的信息。]

于 2012-05-20T17:10:19.660 回答
-1

仅适用于 ARC

您需要将您的块属性声明为strong,将其声明为copy 不是必需的。所以声明应该是:

@property (nonatomic, strong) SaveBlock saveBlock;

为什么不copy呢?

当传递给您initWithSaveBlock:的块时,可能是堆栈分配的,也可能不是. 无论哪种情况,您都需要保留它。如果块在堆栈上,那么保留它会导致它被复制到堆上。如果块已经在堆上,则不需要复制它。因此 usingcopy将起作用,但可能包含冗余副本, usingstrong避免了这种情况。

另请参阅此答案以获取解释。

于 2012-05-20T20:34:05.377 回答