简体   繁体   English

可以在没有__weak对象的块中传递[self anyFunction](iOS 5 + ARC)

[英]Possible to pass [self anyFunction] in blocks without __weak object (iOS 5 + ARC)

Is it possible to pass [self anyFunction] in blocks without a __weak object from self? 是否有可能在没有__weak对象的块中传递[self anyFunction]?

As an example this is valid code from the System Framework: 作为示例,这是来自System Framework的有效代码:

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

You can pass [self anyFunction] in the completion block without a warning. 您可以在完成块中传递[self anyFunction]而不会发出警告。 But if you write your own method with a completion block, the following warning occurs: capturing 'self' strongly in this block is likely to lead to a retain cycle . 但是如果使用完成块编写自己的方法,则会出现以下警告: 在此块中强烈捕获“self”可能会导致保留周期

A working solution is quite simple (iOS 5 + ARC). 工作解决方案非常简单(iOS 5 + ARC)。 Before the block declare: 在块声明之前:

__weak MyClass *weakSelf = self;

and in the completion block you have to call: 在完成块中你必须打电话:

[weakSelf anyFunction];

But, back to my Question: Why there is no need in the System Framework APIs to use a __weak object and to use self without any warnings. 但是,回到我的问题:为什么System Framework API中不需要使用__weak对象并且在没有任何警告的情况下使用self And how to implement a method without the need of a __weak object in the block? 以及如何在块中不需要__weak对象的情况下实现方法?

Thank you for your effort. 感谢你的付出。

The blocks which throw up the error are ones where you capture the objects that own the block. 抛出错误的块是捕获拥有块的对象的块。 For example 例如

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

or 要么

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

but

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

Because an object retains its blocks, and a block retains it's objects. 因为一个对象保留了它的块,一个块保留了它的对象。 So in both these cases, the object which performs the block owns the block, which also owns the object. 因此,在这两种情况下,执行块的对象拥有块,该块也拥有该对象。 So you have a loop - a retain cycle. 所以你有一个循环 - 一个保留周期。 which means the memory is leaked. 这意味着内存泄露。

In the example you have given - you're looking at a class method . 在您给出的示例中 - 您正在查看类方法 You're calling the block on a UIView class, not a UIView object. 您在UIView类上调用块,而不是UIView对象。 A class has no memory associated with it. 类没有与之关联的内存。 And you are probably calling this function from a controller, so the self reference is being retained by the block, but there is no loop because self is not retaining the block. 你可能正在从一个控制器调用这个函数,所以块保留了self引用,但是没有循环,因为self没有保留块。

In the same way that, you may have noticed, not all objects that are used in the block need to be weakly referenced - just the ones that cause a retain cycle. 就像你可能注意到的那样,并非所有在块中使用的对象都需要被弱引用 - 只是导致保留周期的对象。

On code that I need to compile potentially with or without ARC, or with or without the newer compilers, I do the following ... functionally it's the same as what you've listed already, but it avoids the__weak and also avoids the retain release cycles: 对于我需要使用或不使用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;
}];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM