我对使用自我内部块感到困惑,我浏览了一些Apple的文档,但仍然无法找到正确的答案。
有些人总是说在内部块中使用弱自我,但有些人说在复制的块中使用弱自我,而不是总是使用它们。
样本1:
self.handler = ^(id response, NSError *error)
{
self.newresponse = response; //use weak self here
};
样本2:
使用弱自我;
__weak myViewController *weakSelf = self;
[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
[weakSelf.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];
//in above is it use of weak is neassary
}
completion:^(BOOL finished)
{
}];
没有弱自我;
__weak myViewController *weakSelf = self;
[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
[myViewController.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];
}
completion:^(BOOL finished)
{
}];
在上面的样本中,哪些是正确的......? **我正在使用ARC
答案 0 :(得分:76)
如果self
将保留该块的引用,则您应该只使用对self
的弱引用。
在您的示例中,您未在self
中保留对块的引用,您只使用与UIView animateWithDuration:
内联的块,因此无需使用__weak myViewController *weakSelf = self;
}
为什么会这样?因为块将保留对使用块的类中使用的任何变量的强引用。这包括self
。现在,如果类实例本身保持对块的强引用,并且块保持对类实例的强引用,则会有一个保留周期,这将导致内存泄漏。
答案 1 :(得分:10)
以下是一些演示@WDUK答案的代码:
typedef void (^SimpleBlock)();
@interface ObjectThatRetainsBlock : NSObject
@property(nonatomic, strong) SimpleBlock block;
@end
@implementation ObjectThatRetainsBlock
- (instancetype)init {
self = [super init];
if (self) {
self.block = ^{ NSLog(@"Running block in %@", self); };
self.block();
}
return self;
}
- (void)dealloc {
NSLog(@"ObjectThatRetainsBlock is deallocated.");
}
@end
@interface ObjectThatDoesNotRetainBlock : NSObject
@end
@implementation ObjectThatDoesNotRetainBlock
- (instancetype)init {
self = [super init];
if (self) {
SimpleBlock block = ^{ NSLog(@"Running block in %@", self); };
block();
}
return self;
}
- (void)dealloc {
NSLog(@"ObjectThatDoesNotRetainBlock is deallocated.");
}
@end
- (void)test {
ObjectThatRetainsBlock *objectThatRetainsBlock =
[[ObjectThatRetainsBlock alloc] init];
ObjectThatDoesNotRetainBlock *objectThatDoesNotRetainBlock =
[[ObjectThatDoesNotRetainBlock alloc] init];
}
test
方法打印:
Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50>
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50>
ObjectThatDoesNotRetainBlock is deallocated.
观察init
ObjectThatDoesNotRetainBlock
block
方法,我们创建block
作为ivar,但当test
超出范围时,我们不保留参考它。
在objectThatDoesNotRetainBlock
方法中,当两个对象超出范围时,请注意objectThatRetainsBlock
已取消分配,因为它不是保留周期的一部分。
另一方面,{{1}}没有被释放,因为它是保留周期的一部分。它保留了超出方法调用范围的块。
如果您需要其他说明,请参阅this answer。