iPhone阻止访问对象引用的范围混淆

iPhone阻止访问对象引用的范围混淆,iphone,closures,objective-c-blocks,Iphone,Closures,Objective C Blocks,大多数记录在案的块使用示例都演示了使用简单变量的闭包,但我对访问周围代码中存在的对象的任何尝试都感到困惑。例如,这会以一种丑陋、无益的方式崩溃: @interface VisualizerPreset : EyeCandyPreset { float changeSourceRate; float (^frontPanelSlider2DisplayValueBlock)(void); } .... VisualizerPreset *it; it = [[Visual

大多数记录在案的块使用示例都演示了使用简单变量的闭包,但我对访问周围代码中存在的对象的任何尝试都感到困惑。例如,这会以一种丑陋、无益的方式崩溃:

@interface VisualizerPreset : EyeCandyPreset {
    float changeSourceRate;
    float (^frontPanelSlider2DisplayValueBlock)(void);   
}

....

VisualizerPreset *it;
it = [[VisualizerPreset alloc] init];
it.changeSourceRate = 0.4;

it.frontPanelSlider2DisplayValueBlock = ^(void) {
    return it.changeSourceRate; 
};

....


// this crashes
NSLog(@"%f",it.frontPanelSlider2DisplayValueBlock());

一个可能的原因是你失去了街区。块是在堆栈中创建的,而不是在堆中创建的。因此,如果你想保留块,你必须复制它;这将在堆中创建块的副本

float(^aVar)=[^{return 0.0;}copy]

当然,您还必须稍后发布它


小心谁拥有区块的副本。在块内,所有参照对象都将自动保留。因此很容易创建一个参考循环。可以使用_块修改器解决此问题。读一下这个

< P>一个可能的原因是你丢失了这个块。块是在堆栈中创建的,而不是在堆中创建的。因此,如果你想保留块,你必须复制它;这将在堆中创建块的副本

float(^aVar)=[^{return 0.0;}copy]

当然,您还必须稍后发布它


小心谁拥有区块的副本。在块内,所有参照对象都将自动保留。因此很容易创建一个参考循环。可以使用_块修改器解决此问题。考虑阅读这个

,你试过用**块存储修饰符来声明引用的变量吗?i、 e._块可视化设置*it;谢谢,是的,我试过了,没有改变。你试过用块存储修饰符声明引用的变量吗?i、 e._块可视化设置*it;谢谢,是的,我试过了,没变,就是这样!我已将我的区块声明为“转让”财产,而不是“保留”。令人费解的是,只要没有引用封闭范围中的变量,它就可以正常工作。谢谢你的帮助!没问题。当您访问已经从内存中释放的数据(本例中为块)时,行为未定义;它可能会导致分割错误(崩溃),读取虚假的内容,甚至是正确的内容,谁知道呢。这就是为什么很难立即找到bug的原因。因此,当你的应用程序行为异常时,尝试NSZombieEnabled模式,因为当你访问一个发布的对象时,它会给你一个日志。谢谢,这是另一个很酷的技巧。此外,对于记录,如果要定义一个块作为特性使用,则最好使用“复制”而不是“保留”。这就是我从医生那里收集到的,有意义吗?据我所知,是的。因为一个块是在堆栈中分配的,所以我猜想一旦堆栈被释放,不管引用计数机制如何(即方法到达其作用域的末尾),它都将被丢弃。所以你需要在堆里复制一份,就是这样!我已将我的区块声明为“转让”财产,而不是“保留”。令人费解的是,只要没有引用封闭范围中的变量,它就可以正常工作。谢谢你的帮助!没问题。当您访问已经从内存中释放的数据(本例中为块)时,行为未定义;它可能会导致分割错误(崩溃),读取虚假的内容,甚至是正确的内容,谁知道呢。这就是为什么很难立即找到bug的原因。因此,当你的应用程序行为异常时,尝试NSZombieEnabled模式,因为当你访问一个发布的对象时,它会给你一个日志。谢谢,这是另一个很酷的技巧。此外,对于记录,如果要定义一个块作为特性使用,则最好使用“复制”而不是“保留”。这就是我从医生那里收集到的,有意义吗?据我所知,是的。因为一个块是在堆栈中分配的,所以我猜想一旦堆栈被释放,不管引用计数机制如何(即方法到达其作用域的末尾),它都将被丢弃。因此,您需要在堆中创建一个副本。