为什么 UIAlertController 会用 self 创建一个保留周期?
Why does UIAlertController create a retain cycle with self?
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
我了解周期。 self
保留了UIAlertController
,UIAlertController
保留了UIAlertAction
,UIAlertAction
保留了self
我的意思是内部不能将此 class 设计为在其中一个 UIAlertActions 运行?
-
澄清一下,我知道可以通过使用对 self 的弱引用来避免这个问题。
我要问的是,为什么 UIAlertController
在用户选择了一个动作后不直接将所有动作(以及它们的处理程序块)归零。这将打破循环并避免我们需要做的整个弱者舞蹈。
像这样...
@implementation UIAlertController
...
// An action button was pressed
- (void)actionSelectedIndex:(NSInteger)index
{
UIAlertAction *action = self.actions[index];
action.handler(action); // Run the action handler block
self.actions = nil; // Release all the actions
}
问题不是 UIAlertController 是如何设计的,而是块是如何工作的,即它 captures/retains 引用对象,除非引用变量被标记为弱。
我认为将块代码从 [self doSomething];
更改为 [weakSelf doSomething];
应该可以修复保留周期。 weakSelf
变量可以在创建动作之前声明,如下所示:
__weak YourViewCOntrollerClass *weakSelf = self;
实际上当我们在块中使用强实例时(就像你在使用 self 一样),它会创建单独的副本增加保留计数。之后 class 通过调用 dealloc 方法减少保留计数。但不能使它归零。
弱引用在使用后释放计数。所以,像这样创建弱引用:
__weak __typeof(self)weakSelf = self;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[weakSelf doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
这里的问题和答案让我感到困惑,这是我搜索结果的顶部,所以我想澄清一下:
示例中没有保留循环,因此在这种情况下不需要创建"weak self"。唯一存在保留周期的情况是 self 对 alert 有很强的引用。
UIAlertController 被设计为在执行后释放所有内容,前提是您不持有对它的强引用。
我尝试了样本 class 中的示例,并在控制器弹出时成功调用了 dealloc。
举例总结:
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//No retain cycle, no need for weak self
[self doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
对
//assume this is a strong reference
self.alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
__weak __typeof(self)weakSelf = self;
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//Need a weakSelf to avoid retain cycle
[weakSelf doSomething];
}];
[self.alert addAction:action];
[self presentViewController:self.alert animated:YES completion:nil];
旁注:假设在将 self 放入块中时总是需要对 self 使用弱引用是错误的。
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
我了解周期。 self
保留了UIAlertController
,UIAlertController
保留了UIAlertAction
,UIAlertAction
保留了self
我的意思是内部不能将此 class 设计为在其中一个 UIAlertActions 运行?
-
澄清一下,我知道可以通过使用对 self 的弱引用来避免这个问题。
我要问的是,为什么 UIAlertController
在用户选择了一个动作后不直接将所有动作(以及它们的处理程序块)归零。这将打破循环并避免我们需要做的整个弱者舞蹈。
像这样...
@implementation UIAlertController
...
// An action button was pressed
- (void)actionSelectedIndex:(NSInteger)index
{
UIAlertAction *action = self.actions[index];
action.handler(action); // Run the action handler block
self.actions = nil; // Release all the actions
}
问题不是 UIAlertController 是如何设计的,而是块是如何工作的,即它 captures/retains 引用对象,除非引用变量被标记为弱。
我认为将块代码从 [self doSomething];
更改为 [weakSelf doSomething];
应该可以修复保留周期。 weakSelf
变量可以在创建动作之前声明,如下所示:
__weak YourViewCOntrollerClass *weakSelf = self;
实际上当我们在块中使用强实例时(就像你在使用 self 一样),它会创建单独的副本增加保留计数。之后 class 通过调用 dealloc 方法减少保留计数。但不能使它归零。 弱引用在使用后释放计数。所以,像这样创建弱引用:
__weak __typeof(self)weakSelf = self;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[weakSelf doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
这里的问题和答案让我感到困惑,这是我搜索结果的顶部,所以我想澄清一下:
示例中没有保留循环,因此在这种情况下不需要创建"weak self"。唯一存在保留周期的情况是 self 对 alert 有很强的引用。
UIAlertController 被设计为在执行后释放所有内容,前提是您不持有对它的强引用。
我尝试了样本 class 中的示例,并在控制器弹出时成功调用了 dealloc。
举例总结:
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//No retain cycle, no need for weak self
[self doSomething];
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
对
//assume this is a strong reference
self.alert = [UIAlertController alertControllerWithTitle:@"alert" message:nil preferredStyle:UIAlertControllerStyleAlert];
__weak __typeof(self)weakSelf = self;
UIAlertAction *action = [UIAlertAction actionWithTitle:@"action" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//Need a weakSelf to avoid retain cycle
[weakSelf doSomething];
}];
[self.alert addAction:action];
[self presentViewController:self.alert animated:YES completion:nil];
旁注:假设在将 self 放入块中时总是需要对 self 使用弱引用是错误的。