iOS: 视图控制器在解雇时没有释放
iOS: View controllers are not releasing when dismissing
我像这样将当前控制器解散到我的根控制器。
[navigationController popToRootViewControllerAnimated:YES];
但是,导航控制器中的所有视图控制器都没有被释放(我可以判断是因为控制器 类 中的方法被调用了两次并且没有调用 dealloc 方法)。我需要关于如何做才能弄清楚为什么会发生这种情况的建议。是否有一种特定的方式我需要关闭控制器或者可能发生了其他事情。我正在使用 ARC。
这可能是由于多种原因造成的,但您很可能持有指向您正在弹出的 viewController
的强指针。发生的一种情况是,如果一个 viewController
是另一个 viewController
的 delegate
,而 delegate
属性 是 Strong
,那么两个 viewController
彼此保持强指针。
确保没有任何其他对象持有指向您要弹出的 viewController
的强指针。
你弹出的控制器,它是从一个实际存在的viewController
中保留下来的。就这样。您有 2 个解决方案:
当您按下 viewController
时,就地创建它:
UIViewController *vc = [UIViewController initWith...];
[navigationController pushViewController:vc animated:YES];
另一个解决方案是有一个 weak
引用:
//Property in the interface
@property (nonatomic, weak) UIViewController *vc;
//In the method
_vc = [UIViewController initWith...];
[navigationController pushViewController:vc animated:YES];
当 viewController
弹出时,没有其他引用,将被释放。
干杯!
除了持有对委托的强引用的可能性之外,您还应该检查任何使用视图控制器的块,并且在块内部始终使用对该块的弱引用。
来自苹果 docs:
假设您要发出 HTTP 请求并在视图控制器的视图上显示您从服务器获得的一些用户信息。
- (void)requestUserInfo
{
[self.client makeGETRequest:@"http://example.org/user/1/" usingBlock:^(User *user, NSError *error) {
if (error) {
[self.errorView displayWithError:error];
}
else {
self.userView.user = user;
[self.userView setNeedsLayout];
}
}];
}
在这种情况下,当用户厌烦等待 return 结果请求并点击 "Back" 按钮关闭页面时,视图控制器将不会被释放,直到请求加载完成并执行块。您可以通过覆盖 dealloc
.
自己查看
因此,除非需要,否则请始终在块内使用 __weak
对 self
的引用。
- (void)requestUserInfo
{
__weak UIViewController *weakSelf = self;
[self.client makeGETRequest:@"http://example.org/user/1/" usingBlock:^(User *user, NSError *error) {
if (error) {
[weakSelf.errorView displayWithError:error];
}
else {
weakSelf.userView.user = user;
[weakSelf.userView setNeedsLayout];
}
}];
}
我像这样将当前控制器解散到我的根控制器。
[navigationController popToRootViewControllerAnimated:YES];
但是,导航控制器中的所有视图控制器都没有被释放(我可以判断是因为控制器 类 中的方法被调用了两次并且没有调用 dealloc 方法)。我需要关于如何做才能弄清楚为什么会发生这种情况的建议。是否有一种特定的方式我需要关闭控制器或者可能发生了其他事情。我正在使用 ARC。
这可能是由于多种原因造成的,但您很可能持有指向您正在弹出的 viewController
的强指针。发生的一种情况是,如果一个 viewController
是另一个 viewController
的 delegate
,而 delegate
属性 是 Strong
,那么两个 viewController
彼此保持强指针。
确保没有任何其他对象持有指向您要弹出的 viewController
的强指针。
你弹出的控制器,它是从一个实际存在的viewController
中保留下来的。就这样。您有 2 个解决方案:
当您按下
viewController
时,就地创建它:UIViewController *vc = [UIViewController initWith...]; [navigationController pushViewController:vc animated:YES];
另一个解决方案是有一个
weak
引用://Property in the interface @property (nonatomic, weak) UIViewController *vc; //In the method _vc = [UIViewController initWith...]; [navigationController pushViewController:vc animated:YES];
当 viewController
弹出时,没有其他引用,将被释放。
干杯!
除了持有对委托的强引用的可能性之外,您还应该检查任何使用视图控制器的块,并且在块内部始终使用对该块的弱引用。
来自苹果 docs:
假设您要发出 HTTP 请求并在视图控制器的视图上显示您从服务器获得的一些用户信息。
- (void)requestUserInfo
{
[self.client makeGETRequest:@"http://example.org/user/1/" usingBlock:^(User *user, NSError *error) {
if (error) {
[self.errorView displayWithError:error];
}
else {
self.userView.user = user;
[self.userView setNeedsLayout];
}
}];
}
在这种情况下,当用户厌烦等待 return 结果请求并点击 "Back" 按钮关闭页面时,视图控制器将不会被释放,直到请求加载完成并执行块。您可以通过覆盖 dealloc
.
因此,除非需要,否则请始终在块内使用 __weak
对 self
的引用。
- (void)requestUserInfo
{
__weak UIViewController *weakSelf = self;
[self.client makeGETRequest:@"http://example.org/user/1/" usingBlock:^(User *user, NSError *error) {
if (error) {
[weakSelf.errorView displayWithError:error];
}
else {
weakSelf.userView.user = user;
[weakSelf.userView setNeedsLayout];
}
}];
}