总是将自我的弱引用传递给ARC中的块?

我对Objective-C中的块使用有点困惑。 我目前使用ARC,并且在我的应用中有相当多的块,现在总是指self而不是它的弱引用。 这可能是这些块保持self并防止它被交易的原因吗? 问题是,我应该总是在一个块中使用selfweak引用吗?

-(void)handleNewerData:(NSArray *)arr
{
    ProcessOperation *operation =
    [[ProcessOperation alloc] initWithDataToProcess:arr
                                         completion:^(NSMutableArray *rows) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateFeed:arr rows:rows];
        });
    }];
    [dataProcessQueue addOperation:operation];
}

ProcessOperation.h

@interface ProcessOperation : NSOperation
{
    NSMutableArray *dataArr;
    NSMutableArray *rowHeightsArr;
    void (^callback)(NSMutableArray *rows);
}

ProcessOperation.m

-(id)initWithDataToProcess:(NSArray *)data completion:(void (^)(NSMutableArray *rows))cb{

    if(self =[super init]){
        dataArr = [NSMutableArray arrayWithArray:data];
        rowHeightsArr = [NSMutableArray new];
        callback = cb;
    }
    return self;
}

- (void)main {
    @autoreleasepool {
        ...
        callback(rowHeightsArr);
    }
}

这不仅有助于把重点放在strongweak的讨论的一部分。 而是专注于周期部分。

保留周期是当对象A保留对象B并且对象B保留对象A时发生的循环。在这种情况下,如果任一对象被释放:

  • 对象A不会被释放,因为对象B持有对它的引用。
  • 但只要对象A引用它,对象B就不会被释放。
  • 但是对象A永远不会被释放,因为对象B持有对它的引用。
  • 无限广告
  • 因此,这两个对象只会在程序的整个生命周期中留存下来,尽管如果一切正常,它们应该被释放。

    所以,我们担心的是保留周期,并且没有任何关于自己创建这些周期的块。 这不是一个问题,例如:

    [myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
       [self doSomethingWithObject:obj];
    }];
    

    该块保留self ,但self不保留该块。 如果一个或另一个被释放,则不会创建循环,并且所有内容都应该被释放。

    你遇到麻烦的地方就像是:

    //In the interface:
    @property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);
    
    //In the implementation:
    [self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
      [self doSomethingWithObj:obj];     
    }];
    

    现在,你的对象( self )对块有明确的strong引用。 该块对self有一个隐含的强烈的参照。 这是一个循环,现在这两个对象都不会被正确释放。

    因为,在这样的情况下, self定义已经具备了strong参考块,它通常是最容易通过做一个明确的弱引用来解决self的块使用:

    __weak MyObject *weakSelf = self;
    [self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
      [weakSelf doSomethingWithObj:obj];     
    }];
    

    但是,这不应该是你在处理self块时遵循的默认模式 ! 这应该只用于打破本来和块之间的保留周期。 如果你在任何地方都采用这种模式,那么你会冒着将self被释放后被执行的东西传递给块的风险。

    //SUSPICIOUS EXAMPLE:
    __weak MyObject *weakSelf = self;
    [[SomeOtherObject alloc] initWithCompletion:^{
      //By the time this gets called, "weakSelf" might be nil because it's not retained!
      [weakSelf doSomething];
    }];
    

    你不必总是使用弱引用。 如果你的块没有被保留,但被执行然后被丢弃,你可以强烈地捕获自己,因为它不会创建保留周期。 在某些情况下,你甚至希望块保持自己,直到块完成,所以它不会过早地解除分配。 但是,如果您强烈地捕获该块,并在捕获自我内部,它将创建一个保留周期。


    我完全同意@jemmons。

    “但是,这不应该是你在处理自称的块时遵循的默认模式!这应该只用于打破本来和块之间的保留循环,如果你想在每个地方采用这种模式,那么冒着将自己被释放后被执行的东西传递给自己的风险。“

    //SUSPICIOUS EXAMPLE:
    __weak MyObject *weakSelf = self;
    [[SomeOtherObject alloc] initWithCompletion:^{
      //By the time this gets called, "weakSelf" might be nil because it's not  retained!
      [weakSelf doSomething];
    }];
    

    为了解决这个问题,人们可以定义一个关于块内部weakSelf的强有力的参考。

    __weak MyObject *weakSelf = self;
    [[SomeOtherObject alloc] initWithCompletion:^{
       MyObject *strongSelf = weakSelf;
      [strongSelf doSomething];
    }];
    
    链接地址: http://www.djcxy.com/p/37673.html

    上一篇: Always pass weak reference of self into block in ARC?

    下一篇: When and how should I use a ThreadLocal variable?