Is it possible to pass [self anyFunction] in blocks without a __weak object from self?
在没有弱对象的情况下,是否有可能在块中传递[self anyFunction] ?
As an example this is valid code from the 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. 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 - anyFunction]。但是,如果您使用完成块编写自己的方法,则会出现以下警告:在此块中强烈捕获“self”可能会导致保留循环。
A working solution is quite simple (iOS 5 + ARC). Before the block declare:
一个有效的解决方案非常简单(ios5 + ARC)。块前声明:
__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. And how to implement a method without the need of a __weak
object in the block?
但是,回到我的问题:为什么在系统框架api中不需要使用__weak对象和使用self而不需要任何警告。如何实现一个方法而不需要块中的__weak对象?
Thank you for your effort.
谢谢你的努力。
2 个解决方案
#1
53
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.
因为对象保留它的块,而块保留它的对象。在这两种情况下,执行block的对象拥有block, block也拥有对象。所以你有一个循环,一个保持循环。这意味着内存泄漏了。
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. 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.
在您给出的示例中——您正在查看一个类方法。你在UIView类上调用block,而不是UIView对象。类没有与之关联的内存。你可能会从控制器调用这个函数,所以self引用被block保留,但是没有循环因为self没有保留block。
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.
同样地,您可能已经注意到,并不是块中使用的所有对象都需要弱引用—只有引起保留循环的对象才需要弱引用。
#2
14
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;
}];
#1
53
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.
因为对象保留它的块,而块保留它的对象。在这两种情况下,执行block的对象拥有block, block也拥有对象。所以你有一个循环,一个保持循环。这意味着内存泄漏了。
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. 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.
在您给出的示例中——您正在查看一个类方法。你在UIView类上调用block,而不是UIView对象。类没有与之关联的内存。你可能会从控制器调用这个函数,所以self引用被block保留,但是没有循环因为self没有保留block。
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.
同样地,您可能已经注意到,并不是块中使用的所有对象都需要弱引用—只有引起保留循环的对象才需要弱引用。
#2
14
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;
}];