是否有必要在块内使用弱引用自我...?

Shi*_*sad 43 cocoa cocoa-touch objective-c-blocks

我对使用自我内部块感到困惑,我浏览了一些Apple的文档,但仍然无法找到正确的答案.

有些人总是说在块内部使用弱自我,但有些人说在复制的块中使用弱自我,而不是总是使用.

样本1:

self.handler = ^(id response, NSError *error)
{
    self.newresponse = response; //use weak self here
};  
Run Code Online (Sandbox Code Playgroud)

样本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)
{

}];
Run Code Online (Sandbox Code Playgroud)

没有弱小的自我;

__weak myViewController *weakSelf = self;

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
    [myViewController.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];

}
completion:^(BOOL finished)
{

}];
Run Code Online (Sandbox Code Playgroud)

在上面的样本中,哪些是正确的......?**我正在使用ARC

WDU*_*DUK 76

self如果self要保留块的引用,则应该只使用弱引用.

在您的示例中,您没有保留对块的引用self,您只使用与内联的块UIView animateWithDuration:,因此不需要使用__weak myViewController *weakSelf = self;

为什么会这样?因为块将保留对使用块的类中使用的任何变量的强引用.这包括self.现在,如果类实例本身保持对块的强引用,并且块保持对类实例的强引用,则会有一个保留周期,这将导致内存泄漏.

  • @jeeva在样本1中,需要对自我**的弱引用.在样本2和3中,不需要对自我**的弱引用. (5认同)
  • 所以在类方法(animateWithDuration)中不需要弱自我,因为自我没有保留或拥有该块我是对的......? (3认同)
  • 谢谢,你的解释完全有道理.但是,我无法解释Apple的示例代码中使用`weakSelf`:http://developer.apple.com/library/ios/#documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/Reference/reference.html%23 // apple_ref/DOC/UID/TP40007099-CH991-SW4 (2认同)

Ros*_*one 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];
}
Run Code Online (Sandbox Code Playgroud)

test方法打印:

Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50>
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50>
ObjectThatDoesNotRetainBlock is deallocated.
Run Code Online (Sandbox Code Playgroud)

观察在init方法中ObjectThatDoesNotRetainBlock,我们创建block为ivar,但是当block超出范围时,我们不会保留对它的引用.

在该test方法中,当两个对象超出范围时,观察它objectThatDoesNotRetainBlock被解除分配,因为它不是保留周期的一部分.

另一方面,objectThatRetainsBlock不会被释放,因为它是保留周期的一部分.它保留了超出方法调用范围的块.

如果您想要另一种解释,请参阅此答案.