Iphone 调试和发布配置之间的不同块行为

Iphone 调试和发布配置之间的不同块行为,iphone,ios,objective-c,automatic-ref-counting,block,Iphone,Ios,Objective C,Automatic Ref Counting,Block,我的程序运行得很好。我向你保证我的生命,0个虫子。我很自豪地尝试将应用程序打包为.ipa文件,以便使用TestFlight将其临时分发给我的beta测试人员 这个程序不起作用。应该发生的动画从未发生过。网络代码中断。把音乐美妙地淡出的按钮根本没用 事实证明,罪魁祸首是新的闪亮的积木。当我在模拟器或设备上测试我的程序时,我使用默认的“调试”构建配置。但当我将其归档以供分发(我相信稍后会提交到应用商店)时,XCode使用了另一种配置,即“Release”。进一步调查,差异是由于优化级别(可以在XCo

我的程序运行得很好。我向你保证我的生命,0个虫子。我很自豪地尝试将应用程序打包为.ipa文件,以便使用TestFlight将其临时分发给我的beta测试人员

这个程序不起作用。应该发生的动画从未发生过。网络代码中断。把音乐美妙地淡出的按钮根本没用

事实证明,罪魁祸首是新的闪亮的积木。当我在模拟器或设备上测试我的程序时,我使用默认的“调试”构建配置。但当我将其归档以供分发(我相信稍后会提交到应用商店)时,XCode使用了另一种配置,即“Release”。进一步调查,差异是由于优化级别(可以在XCode的构建设置中找到):调试使用None(-O0),但发布版使用最快、最小的(-Os)。我几乎不知道,它是最快的,最小的,而且不起作用(tm)。是的,这两种配置之间的块行为不同

因此,我着手解决这个问题。我已经简化了我的“即将改变世界”应用程序,将其简化为赤裸裸的部分,如我附在本文的图片所示。视图控制器有一个初始值为0的实例变量x。如果我们按b键,它将生成一个线程,该线程将持续检查x的值,当x变为1时更改底部标签。我们可以使用按钮a更改x的值

以下是我的简单代码(我使用的是ARC btw):

_x是一个实例变量,因此有理由认为块将使用指向“self”的指针来访问它,而不是在本地副本上。它可以在调试配置上工作

但它在发布版本上不起作用。那么,说到底,该块可能使用的是本地副本?好,让我们明确使用self:

while (self->_x != 1) {
    // keep observing for value change
}
在发行版中也不起作用。好的,让我们直接使用指针访问这个该死的变量:

int *pointerToX = &_x;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    while (*pointerToX != 1) {
        // keep observing for value change
    }
    // other codes
});
还是不行。这时我才明白,智能优化编译器假设在这个多线程的世界中,比较的结果不可能改变,所以它可能会将其替换为“始终为真”或其他伏都教

现在,当我使用这个时,事情又开始起作用了:

while (_x != 1) {
    // keep observing for value change
    NSLog(@"%d", _x);
}
因此,为了绕过编译器优化比较,我求助于制作一个getter:

- (int)x
{
    return _x;
}
然后使用该getter检查值:

while (self.x != 1) {
    // keep observing for value change
}

它现在可以工作了,因为self.x实际上是对一个函数的调用,并且编译器非常有礼貌地让函数实际完成它的工作。然而,我认为这是一个相当复杂的方式来做这么简单的事情。如果你面临着“观察块内值的变化”的任务,你会用其他方式编码它吗?你会用另一种模式吗?非常感谢

如果使用变量而不在循环中修改它,编译器优化可能会导致对变量的实际访问被优化掉,因为可以在编译时预先对语句求值

为了防止这种情况,您可以使用“volatile”关键字,这会阻止编译器应用这种类型的优化


它确实与getter和setter一起工作,因为您需要向实例发送一条消息,作为同步点。

请尝试按如下方式声明x:

__block int _x;

通常会复制块中也使用的变量。这将向编译器指示,如果在块中修改了x,那么更改应该在块外部可见。它可能会解决您的问题。

\uu block
仅适用于本地变量w,volatile关键字有效!我记得曾经在一本C语言书上读过一次,从没想过我会用它!谢谢
__block int _x;