我在使用自身内部块时一直在使用块并熟悉内存管理 非ARC环境
但我有两个具体问题:
1)我明白我可以使用__block来避免保留周期一个保留的块,而后者又可以使用self创建,如下所示:
__block MyClass *blockSelf = self;
self.myBlock = ^{
blockSelf.someProperty = abc;
[blockSelf someMethod];
};
这肯定会避免保留周期,但是通过这样做,我创建了一个自我发布的范围,并最终由其他人解除分配。所以当这种情况发生时,自我就消失了,而且blockSelf指向了垃圾值。在取消分配self之后执行块时可能存在条件,然后块将在尝试使用释放的实例时崩溃。我们怎样才能避免这种情况?如何在块执行时检查blockSelf是否有效,或者在取消分配self时检查块执行是否有效。
2)在类似的行上假设我使用如下的块:
__block MyClass *blockSelf = self;
self.myBlock = ^{
[blockSelf someMethod:blockSelf.someProperty];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
现在可能存在self未释放但在someMethod执行开始之前释放someProperty的情况(当有多个线程时可能会发生这种情况)。即使我做self.someProperty = nil;当它被释放时,myClassProperty不是nil并且指向一些垃圾,因此当执行someMethod时,第一行将导致崩溃。我该如何避免这种情况?
答案 0 :(得分:3)
这与非ARC代码中的其他地方的非归零弱引用相同,例如:代表等(MRC没有将弱引用归零;因此这些是MRC中唯一的弱引用。但是人们仍然能够在ARC前的日子里编写安全代码。)
基本上,解决方案是您需要一张清晰的所有权地图。要么self
负责保持块活着;或其他一些对象负责保持块活着。
例如,对于代表,通常是"父母" object是" child"的代表。宾语;在这种情况下,"父母"对象负责保持"孩子"对象存活,所以"父母"对象将比孩子更长寿#34;对象,因此后引用可以是弱的并且是安全的(因为子对象的方法只能在父对象处于活动状态时由父对象调用)。
另一方面,如果你有一个异步操作,并且该块作为回调被赋予操作,那么通常操作负责保持块。在这种情况下,self
不会保留在块上。该块将保留对self
的强引用,以便在操作完成后,它仍然可以安全地执行它在self
上需要执行的任何操作。实际上,无论对象self
是什么,它都不需要由任何使用它的人保留,因为它是由异步操作间接保留的 - 它可以只是一个创建,触发和忘记那种事。
如果你有一些东西,有时块被self
保持活着,有时还被其他东西保持活着,那么你应该重新思考你的设计。你说"在取消分配self之后执行块时可能存在条件&#34 ;;好吧,你应该描述你的整个设计以及如何发生这种情况。因为通常,对于异步执行的事情,self
不需要保留在块上。
您的代码真的很混乱,没有意义。例如,为什么要分配参数(myClassProperty
)?无论如何,当参数被覆盖时,传递参数的重点是什么?为什么要命名一个局部变量" myClassProperty
"?
我认为您要问的是访问可以在不同线程上更改的属性,以及如何处理内存管理。 (这个问题与块或ARC / MRC无关。它同样是ARC中的一个问题。)
答案是你需要一个原子属性。您可以创建同步属性atomic
,或者如果您知道如何手动实现原子属性。对象指针类型的原子属性需要做的是它的getter不仅需要返回底层变量,还需要保留并自动释放它,并返回结果。 getter中的检索和保留发生在一个关键部分,该部分与setter中的关键部分同步,包括旧值的释放和新值的保留。基本上,这种同步保证了在检索值并将其保留在getter中之间不会在setter中释放该值。并且从getter返回的值将被保留并自动释放,因此保证在范围的持续时间内保持活动状态。
答案 1 :(得分:-2)
解决方案2)
__block MyClass *blockSelf = self;
self.myBlock = ^{
datatype* p = [blockSelf.someProperty retain];
[blockSelf someMethod:p];
[p release];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
1)不知道你如何使用myBlock
。如果仅由self
使用,那么一切都会好的。如果它被其他一些对象使用,那么它也应该保留self
的引用,然后一切都会好的。