【问题标题】:Possible to pass [self anyFunction] in blocks without __weak object (iOS 5 + ARC)可以在没有 __weak 对象的块中传递 [self anyFunction] (iOS 5 + ARC)
【发布时间】:2012-01-25 13:36:32
【问题描述】:

是否可以在没有来自 self 的 __weak 对象的情况下在块中传递 [self anyFunction]?

例如,这是来自系统框架的有效代码:

[UIView animateWithDuration:0.8 animations:^{
            //Do animationStuff
        } completion:^(BOOL finished) {
            [self anyFunction];
 }];

您可以在完成块中传递[self anyFunction] 而不会发出警告。但是,如果您使用完成块编写自己的方法,则会出现以下警告:在此块中强烈捕获 'self' 可能会导致保留循环

一个可行的解决方案非常简单(iOS 5 + ARC)。块声明前:

__weak MyClass *weakSelf = self;

在完成块中你必须调用:

[weakSelf anyFunction];

但是,回到我的问题:为什么系统框架 API 中不需要使用 __weak 对象并在没有任何警告的情况下使用 self。以及如何在块中实现不需要__weak 对象的方法?

感谢您的努力。

【问题讨论】:

    标签: iphone objective-c ios automatic-ref-counting objective-c-blocks


    【解决方案1】:

    引发错误的块是您捕获拥有该块的对象的块。例如

    [object performBlock:^{
        [object performSomeAction]; // Will raise a warning
    }];
    

    [self performBlock:^{
        [self doSomething];    // Will raise a warning
    }];
    

    但是

    [self performBlock:^{
        [object doSomething];    // <-- No problem here
    }];   
    

    因为一个对象保留了它的块,而一个块保留了它的对象。所以在这两种情况下,执行块的对象拥有块,块也拥有对象。所以你有一个循环 - 一个保留循环。这意味着内存泄漏了。

    在您给出的示例中 - 您正在查看 类方法。您在 UIView 类上调用块,而不是 UIView 对象。一个类没有与之关联的内存。而且您可能正在从控制器调用此函数,因此块保留了 self 引用,但没有循环,因为 self 没有保留块。

    同样,您可能已经注意到,并非所有在块中使用的对象都需要被弱引用 - 只是那些导致保留循环的对象。

    【讨论】:

    • 谢谢,我的问题已经澄清。在我的例子中,拥有该块的对象是ivar,因此您必须使用self__weak 对象。但是当我在使用块的函数中声明对象时,self 可以在没有 __weak 对象的情况下传递。这就说得通了。再次感谢。
    • 我发现的是 [self.ivar performBlock:^{ [self doSomething]; }];将导致编译器警告,而 [self performBlock:^{ [self doSomething]; }];不会导致编译器警告。
    • 也许 [self performBlock:^{ [self doSomething];}];应替换为 [self performBlock:^{ [self doSomething];自我=无;}];
    【解决方案2】:

    对于我可能需要编译的代码,无论是否使用 ARC,或者使用或不使用较新的编译器,我都会执行以下操作...在功能上它与您已经列出的相同,但它避免了 __weak 并且还避免了保留发布周期:

    //
    // FOR NON-ARC PROJECTS
    //
    __block __typeof__(self) bself = self;
    [someObject doThingWithBlock:^(id result){
        if (!bself)
            return;
        bself.thingWhich = result;
    }];
    
    ///
    // FOR ARC PROJECTS
    //
    __weak MyClass *bself = self;
    [someObject doThingWithBlock:^(id result){
        if (!bself) 
            return;
        bself.thingWhich = result;
    }];
    

    【讨论】:

    • 在 ARC 下,这可能会导致一个保留周期。 (__block 语义已更改为保留对象。)
    • 没错。我们现在使用 __weak MyClass *bself = self;
    • 添加了 arc 示例,以及我对异步块的错误处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多