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