首页 文章

为什么UIAlertController用self创建一个保留周期?

提问于
浏览
3
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];

我理解 cycle . self 保留 UIAlertControllerUIAlertController 保留 UIAlertActionUIAlertAction 保留 self

What I mean is internally couldn't this class have been designed to release everything after one of the UIAlertActions has been run?

为了澄清,我知道通过使用对自我的弱引用可以避免这个问题 .

我要问的是,一旦用户选择了一个动作,为什么 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
}

3 回答

  • 8

    这里的问题和答案令我感到困惑,这是我的搜索结果,所以我想直接记录:

    示例中没有保留周期,因此在这种情况下不需要创建“弱自我” . 保留周期的唯一时间是自我是否具有强烈的警报参考 .

    UIAlertController被设计为在执行后释放所有内容,前提是您没有强有力的引用 .

    我在示例类中尝试了该示例,并且在控制器的pop上成功调用了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];
    

    VS

    //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];
    

    旁注:假设在将其放入块中时总是需要使用弱引用是错误的 .

  • 1

    问题不在于如何设计UIAlertController,而是块如何工作,即它捕获/保留参考对象,除非引用变量标记为弱 . 我认为将块代码从 [self doSomething]; 更改为 [weakSelf doSomething]; 应该可以修复保留周期 . weakSelf 变量可以在动作创建之前声明,如下所示:

    __weak YourViewCOntrollerClass *weakSelf = self;

  • 1

    实际上当我们在块中使用强实例时(就像你正在使用self),它会创建单独的副本来增加保留计数 . 在该类通过调用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];
    

相关问题