在ARC中总是将自我的弱引用传递给阻塞? [英] Always pass weak reference of self into block in ARC?

查看:95
本文介绍了在ARC中总是将自我的弱引用传递给阻塞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Objective-C中的块使用有点困惑。我目前使用ARC,我的应用程序中有很多块,目前总是指 self 而不是弱引用。可能是这些块保留 self 的原因并防止它被解除分配?问题是,我是否应始终在块中使用 self 参考?

I am a little confused about block usage in Objective-C. I currently use ARC and I have quite a lot of blocks in my app, currently always referring to self instead of its weak reference. May that be the cause of these blocks retaining self and keeping it from being dealloced ? The question is, should I always use a weak reference of self in a block ?

-(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);
    }
}


推荐答案

它有助于不关注讨论的 strong 部分。而是专注于循环部分。

It helps not to focus on the strong or weak part of the discussion. Instead focus on the cycle part.

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

A retain cycle is a loop that happens when Object A retains Object B, and Object B retains Object A. In that situation, if either object is released:


  • 对象A赢了不会被释放,因为对象B拥有对它的引用。

  • 但只要对象A有对它的引用,对象B就不会被释放。

  • 但是对象A永远不会被释放因为对象B拥有对它的引用。

  • ad infinitum

  • Object A won't be deallocated because Object B holds a reference to it.
  • But Object B won't ever be deallocated as long as Object A has a reference to it.
  • But Object A will never be deallocated because Object B holds a reference to it.
  • ad infinitum

因此,这两个对象只会在程序的生命周期中徘徊,即使它们应该在一切正常工作的情况下被解除分配。

Thus, those two objects will just hang around in memory for the life of the program even though they should, if everything were working properly, be deallocated.

所以,我们担心的是保留周期,并且没有关于创建这些周期的块本身。这不是问题,例如:

So, what we're worried about is retain cycles, and there's nothing about blocks in and of themselves that create these cycles. This isn't a problem, for example:

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

该块保留 self ,但 self 不保留该块。如果释放了一个或另一个,则不会创建任何循环,并且所有内容都会按原样释放。

The block retains self, but self doesn't retain the block. If one or the other is released, no cycle is created and everything gets deallocated as it should.

您遇到麻烦的地方如下:

Where you get into trouble is something like:

//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 隐式强引用。这是一个循环,现在这两个对象都不会被正确释放。

Now, your object (self) has an explicit strong reference to the block. And the block has an implicit strong reference to self. That's a cycle, and now neither object will be deallocated properly.

因为在这种情况下, self 按照定义已经有一个 strong 对该块的引用,通常可以通过对 self进行明确的弱引用来解决它表示要使用的块:

Because, in a situation like this, self by definition already has a strong reference to the block, it's usually easiest to resolve by making an explicitly weak reference to self for the block to use:

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

但在处理块时,这不应该是您遵循的默认模式调用 self !这应该只用于打破自我和块之间的保留周期。如果你在任何地方都采用这种模式,你就有可能将块传递给在 self 被解除分配后执行的东西。

But this should not be the default pattern you follow when dealing with blocks that call self! This should only be used to break what would otherwise be a retain cycle between self and the block. If you were to adopt this pattern everywhere, you'd run the risk of passing a block to something that got executed after self was deallocated.

//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];
}];

这篇关于在ARC中总是将自我的弱引用传递给阻塞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆