繁体   English   中英

iOS 4阻止并保留计数

[英]iOS 4 blocks and retain counts

我刚刚开始使用积木和Grand Central Dispatch。 我被告知(并在Apple文档中阅读)任何块中引用的对象都会被保留。

例如:

^{  
    self.layer.transform = CATransform3DScale(CATransform3DMakeTranslation(0, 0, 0), 1, 1, 1);
    self.layer.opacity = 1;
}

“自我”得到保留,因此泄漏。 为了避免这种情况,我需要将self分配给:

__block Object *blockSelf = self;

然后在我的块中使用blockSelf而不是self

我的问题是:当你的块有更多的代码并引用几个对象时会发生什么? 我是否需要将它们全部分配给__block对象? 例如:

^{  
    [self doSomething];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"prevName == %@", artistName];
    [request setEntity:entity];
    [request setPredicate:predicate];

    Object *newObject = [[Object alloc] init];
    [someArray addObject];
    [newObject release];
}

不会。当您的块保留一个保留它的对象时,会出现问题。 您的块将保留它引用的任何对象,但使用__block注释的对象除外。 因此:

// The following creates a retain cycle which will leak `self`:
self.block = ^{
  [self something];
};

self保留blockblock隐含self 如果您引用self实例变量,也会发生这种情况。

// The following avoids this retain cycle:
__block typeof(self) bself = self;
self.block = ^{
  [bself something];
};

__block注释的变量是可变的(对于指针,也就是说,它们指向的地址可以改变); 因此,保留该对象没有任何意义,因为您需要将该对象视为局部变量(例如,它可以被重新分配,影响块范围之外的对象)。 因此, __block不会被块保留。

但是,如果您尝试以某种方式使用此块,现在可能遇到无法预料的问题。 例如,如果您决定以某种方式延迟调用此块,并且在执行该块时已取消分配self ,则程序将崩溃,因为您正在向已释放的对象发送消息。 那么你需要的是一个弱引用,它不是在非垃圾收集环境中开箱即用的!

一种解决方案是使用MAZeroingWeakRef来封装你的块; 这将归零的指针,让你在刚刚结束了将消息发送到nil ,你应该尝试的消息selfself已释放:

MAZeroingWeakRef *ref = [MAZeroingWeakRef refWithTarget:self];
self.block = ^{
  [ref.target something];
};

我还在Objective-C ++中实现了一个弱引用包装器 ,它提供了更轻量级语法的好处:

js::weak_ref<SomeClass> ref = self;
self.block = ^{
  [ref something];
};

因为js::weak_ref是一个类模板,所以你会得到方便的强类型(也就是说,如果你尝试向引用发送一个它似乎没有响应的消息,你将在编译时收到警告) 。 但迈克的MAZeroingWeakReference比我的成熟得多,所以我建议使用他,除非你想弄脏你的手。

要阅读有关__block问题和弱引用用例的更多信息,请阅读使用块避免保留周期,正确方法Jonathan Rentzsch的响应

我会说这取决于你对你的阻碍做了什么。 如果您没有将它存储在任何地方并在定义位置使用它(比如使用块对数组进行排序),那么它将与其中引用的变量一起释放(因为它是在堆栈中创建的并且标记为自动释放)。 如果你将它存储在某个地方(数组,字典或者可能将块传递给其他函数),请copy块并使用autorelease平衡它,然后再传递它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM