我有一种情况,需要使用访问该对象的完成块来初始化对象。为了使这种访问成为可能,该对象被定义为__block。问题在于该对象永远不会被释放。看下面的例子。
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
__block MyViewController* myViewController = [[MyViewController] alloc] initWithCompletion:^{
if (indexPath.row == 0) {
[myViewController.navigationController
pushViewController:[[GoodViewController alloc] init]
animated:YES
];
} else if (indexPath.row == 1) {
[myViewController.navigationController
pushViewController:[[BadViewController alloc] init]
animated:YES
];
}
}];
}
一切都很好,只是从导航堆栈中弹出myViewController的dealloc不会被调用。当我删除__block时,将最终调用dealloc,但这样做会阻止我访问其完成块内的myViewController。如何在没有内存泄漏的情况下访问其自己的完成块中的对象?
您的视图控制器将保留该块,而该块将保留myViewController
,从而创建一个保留周期。
像这样想吧...视图控制器在模块周围放置了一条皮带,以防止它在视图控制器完成之前被取消分配。该块将皮带束缚在视图控制器周围,以防止其取消分配,直到完成该块为止。
在另一个先释放其引用之前,任何一个都不会释放对另一个的引用,从而保持一个循环。
有多种方法可以避免保留周期,具体取决于您使用该块的方式。
在您的情况下,我将让完成块传回该块所连接的视图控制器。这将很容易避免保留对象本身的需要。
MyViewController* myViewController = [[MyViewController] alloc]
initWithCompletion:^(MyViewController *viewController) {
if (indexPath.row == 0) {
[viewController.navigationController
pushViewController:[[GoodViewController alloc] init]
animated:YES
];
} else if (indexPath.row == 1) {
[viewController.navigationController
pushViewController:[[BadViewController alloc] init]
animated:YES
];
}
}];
在MyViewController类中,您只需使用...调用该块。
if (_completionBlock) _completionBlock(self);
在设计界面时,请尝试使其尽可能易于使用,而不会对用户造成不适当的限制。在这种情况下,通过将控制器作为参数传递回该块,可以让用户编写不必担心在控制器和块之间创建的保留周期的代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句