阻止回调崩溃

时间:2012-05-20 16:44:38

标签: iphone objective-c ios objective-c-blocks

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

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

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;

2 个答案:

答案 0 :(得分:7)

您需要将阻止属性声明为copy

@property(nonatomic, copy) SaveBlock saveBlock;

您无法使用assignstrong。原因是你需要确保你有自己的块副本。传入的那个可能在堆栈框架上,当你运行块时可能会消失。因此,您需要触发Block_copy()以确保将块复制到堆中(或者只有在已经存在的情况下才保留)。

[注意:这个解释非常简洁。如果你想完全理解它,我建议你去读一下块运行时。]

答案 1 :(得分:-1)

仅适用于ARC

您需要将阻止属性声明为strong,并将其声明为copy 不需要。声明应该是:

@property (nonatomic, strong) SaveBlock saveBlock;

为什么不copy

当传递给你的initWithSaveBlock:时,该块可能是堆栈分配的,或它可能不是。在任何一种情况下,您都需要保留它。如果块在堆栈上,那么保留它将使其被复制到堆上。如果块已经在堆上,则无需复制。因此,使用copy将起作用,但可能包含冗余副本,使用strong可以避免这种情况。

另请参阅this answer以获取解释。