Objective c 保留iOS块的问题
以前也有人问过类似的问题,但我无法用这些答案解决我目前的问题 情况:Objective c 保留iOS块的问题,objective-c,ios,objective-c-blocks,retaincount,Objective C,Ios,Objective C Blocks,Retaincount,以前也有人问过类似的问题,但我无法用这些答案解决我目前的问题 情况: CustomType *Object; BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) { //Calculate Average from Total and Pulse Total /= Pulse; [Trigger setValue:Total]; }; Objec
CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};
Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
[Array addObject:Object]; //Adds to collection.
目前的问题是一个保留周期,您可能已经想到了这一点。Object
在addCallback
中保留对块的引用,而块doAverage
保留对对象的引用
使用实例变量是不可能的,因为我想对多个对象重用变量Object
。(临时变量)。
使用局部变量会导致保留计数。
使用\u block CustomType*Object
也不起作用,因为无论出于何种原因触发器
在实际调用回调后都会以nil结束
有什么想法吗
我有一个临时解决方案,但它似乎有点……不太好。尝试将对象声明为
__weak CustomType *Object
如前所述,这个答案相当粗糙,如果有人能给我指出一个更好的方向,我将非常高兴。
显然,基本数据类型与\u块
变量的组合起到了作用,尽管这有点复杂
void *Ptr; //Variable for Block.
__block CustomType *Obj; //Function variable, mutable by block.
BOOL (^doAverage)(void *, int, int) = ^(void *Trigger, int Total, int Pulse) {
CustomType *T = (CustomType *)Trigger; //Conversion
//Calculate Average from Total and Pulse
Total /= Pulse;
[T setValue:Total];
};
//Convenience method.
CustomObject *(^Add)(CustomObject *) = ^(CustomObject *)NewObject {
[Array addObject:NewObject];
Obj = NewObject; //Assigns to the local block-Variable.
return Obj;
};
Ptr = Add([CustomObject CreateObject]); //Creates the Object, and adds it to the array.
[Obj addCallback:^{ return doAverage(Ptr, 56, 32); }];
由于Ptr
是一种基本类型,因此它不会被保留,也不必被释放。同时,它假定所讨论的对象的地址,从而将其加倍
一旦对象被释放,带指针的块也被释放,一切都很好。
调用块后,需要将指针强制转换为所讨论的类型,但这只是一个小问题
Add
当然是可选的,但我不喜欢语法Ptr=Obj=[CustomObject CreateObject]代码>如果部署目标至少为iOS 5(或OS X 10.7),则可以使用“将弱引用归零”:
(我使用了makeObject
而不是CreateObject
作为“工厂方法”的名称,因为名称中带有“create”的方法预期返回(+1)retain count对象,而不是自动删除的对象。)
\u弱
引用不会增加保留计数,因此不会创建保留周期。如果对象
由于对它的最后一个强引用消失而被销毁,则weakSelf
被设置为nil
。在块内创建一个强引用,该强引用或者指向对象(如果该对象仍然存在),或者是nil(如果该对象不再存在)
如果我正确理解您的代码,那么如果对象已被释放,则不会调用回调。在这种情况下,一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
有几件事。首先,我想看看您的addCallback:
方法。有可能是您错误地实现了它。例如,如果存储块以供以后使用,则必须复制该块。如果它是错误的,那么所有的赌注都在剩下的东西上了
使用_block CustomType*对象也不起作用,因为对于
无论什么原因,一旦回调被实际调用,触发器将以nil结束
打电话来
因此,如果它是nil
,那么这意味着您将nil
分配到对象的某个地方
CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};
Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
Taylor说->“然而,我想要的是有问题的‘对象的非保留副本’,一旦解除分配相应对象,该副本将‘丢失’。”
除非您在addCallback([^{}copy])上或内部使用copy,否则此代码似乎不会导致retain循环
代码中使用的副本在哪里?在addCallback里面?如果是这样的话:
addCallback(o) {
o = [o copy];
o();
then do a [o release]; when you done with a block object.. do not release it in dealloc()
}
如果你从未在任何地方使用过copy,没什么好担心的。。这一切都发生在堆栈中,这意味着除非它不是一个全局的,否则根本就没有保留的cyles
如果有零售环节,不要使用_块_弱等,而是释放块末尾的任何对象。。记住,没有拷贝就没有保留周期 XCode向我抛出一个警告:\u不能在自动变量上指定弱属性
。这将在分配对象后立即释放该对象。或者是因为它是一个自动删除的对象,一旦它被自动删除。我要指出的是,始终将对象设置为小写,并且第一行中缺少一个指针。@nsaddct谢谢指针,我解决了这个问题。关于小写…为什么?你看,我已经长大了C++,从而有利于CAMELSE符号。(大写字母和每个起始词)这是大多数编程语言的标准。类>以大写字母开头,变量>以小写字母开头,可读性好得多,因为可以对类和对象调用方法。@NSAddict啊,我明白了。我将来会记住这一点,现在请你耐心等待。谢谢。哦,骆驼的情况也很重要,这只是第一个角色假设他用的是ARC,那is@newacct:是的,我是这么想的__无ARC时不安全未恢复可用,但此处可能没有帮助。\u不安全未恢复
此处不会执行您在MRC下想要的操作。它仍将保留。您需要在MRC下使用\u block
。对不起,我没有使用ARC。我喜欢保持我的东西“手动”和“受控”。(另外,如果我现在使用ARC,我需要重构整个代码)@ATaylor:我的答案可能不会有帮助。我是如此习惯于ARC,以至于在试图解决您的问题时,我没有想到MRC。这甚至不是有效的代码。Add
块具有返回类型,但在body@newacct我请求你的原谅。我一定是在复制代码时忘记了返回语句。是的,我注意到“复制”是必须的。这就是为什么addCallback
创建一个对象(容器)并使用[Block copy]
保存引用的原因。是的,分配一个“nil”值是完全可能的。然而,我想要的是有问题的“对象的非保留副本”,一旦相应的obje出现,该副本将“丢失”
CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};
Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
addCallback(o) {
o = [o copy];
o();
then do a [o release]; when you done with a block object.. do not release it in dealloc()
}