Cocoa touch 是否有必要使用弱引用来始终位于块内的self。。?
我对self-inside块的使用感到困惑,我浏览了一些苹果的文档,但仍然找不到正确的答案 有些人总是说在块中使用弱自我,但有些人说在复制的块中使用弱自我,而不是总是必须使用 样本1:Cocoa touch 是否有必要使用弱引用来始终位于块内的self。。?,cocoa-touch,cocoa,objective-c-blocks,Cocoa Touch,Cocoa,Objective C Blocks,我对self-inside块的使用感到困惑,我浏览了一些苹果的文档,但仍然找不到正确的答案 有些人总是说在块中使用弱自我,但有些人说在复制的块中使用弱自我,而不是总是必须使用 样本1: self.handler = ^(id response, NSError *error) { self.newresponse = response; //use weak self here }; 样本2: 利用弱自我 __weak myViewController *weakSelf = se
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)
{
}];
没有软弱的自我
__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如果
self
将保留块的引用,则只应使用对self
的弱引用
在您的示例中,您没有在self
中保留对块的引用,您只使用与UIView animateWithDuration:
内联的块,因此无需使用\uu弱myViewController*weakSelf=self代码>
为什么会这样?因为块将保留对使用该块的类中它使用的任何变量的强引用。这包括self
。现在,如果类实例本身保持对该块的强引用,而该块保持对该类实例的强引用,则存在一个保留周期,这将导致内存泄漏。以下是一些代码,演示@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];
}
测试方法打印:
Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50>
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50>
ObjectThatDoesNotRetainBlock is deallocated.
运行块插入
运行阻塞
释放不包含块的对象。
请注意,在不包含块的对象的init
方法中,我们将block
创建为ivar,但当块
超出范围时,我们不会保留对它的引用
在test
方法中,当两个对象超出范围时,观察不包含块的对象被解除分配,因为它不是保留周期的一部分
另一方面,objectthatRetainBlock
不会被释放,因为它是保留周期的一部分。它将块保留在方法调用的范围之外
如果您需要另一种解释,请参阅。可能的类内方法(animateWithDuration)的副本也不需要弱self,因为self没有保留或拥有该块,对吗…?在示例1中self.handler=^(id response,NSError*error){self.newresponse=response;//在此处使用弱self};我们需要一周的self,因为block被self保留,self被block保留,所以它是保留循环…?@jeeva在样本1中,需要一个self的弱引用。在示例2和3中,不需要对self进行弱引用。谢谢,您的解释完全有道理。然而,我无法解释在苹果的示例代码中使用weakSelf
:一个好的观点,我忽略了self
没有保留块的事实;它只是对框架的回调。道歉。我相信在这种情况下,这是一种防御编码。声明它弱没有什么坏处,因为从概念上讲,在这里保留self
是没有意义的(为什么回调应该延长self
?)。这也意味着,如果有人想稍后存储块,他们不需要更改其内容。最终,虽然在这里声明它弱不是防止泄漏所必需的,但它是一些程序员用来确保健壮性的一种方式。