3

我有一个问题我在 2 天内无法解决,它只发生在发布版本中,我在调试版本中运行它时没有任何问题。

但我认为这是因为一个没有被执行的块。我有这样的崩溃报告:

3   libdispatch.dylib               0x375d1c34 _dispatch_Block_copy + 8
4   libdispatch.dylib               0x375dc4ca dispatch_async$VARIANT$up + 6
5   Koldkrigsspionen                0x00020ef2 -[NOAudioManager audioPlayerDidFinishPlaying:successfully:] (NOAudioManager.m:807)

audioPlayerDidFinishPlaying:successfully 的方法是这样的:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    if (musicPlayerCompletionBlock)
        dispatch_async(dispatch_get_main_queue(), musicPlayerCompletionBlock);
}

块设置如下:

- (void)setMusicCompletionBlock:(void (^)(void))theBlock 
{ 
    musicPlayerCompletionBlock = theBlock; 
} 

像这样在头文件中:

void (^musicPlayerCompletionBlock) (void);
4

1 回答 1

8

您需要在您的设置器中复制该块。块从堆栈开始,在复制之前不会移动到堆中。

它在调试版本中“工作”,因为未启用优化器,因此编译器不会积极重用堆栈。即巧合。如果您要在块创建和调用之间添加一个或两个方法调用,它可能会开始崩溃。

我建议您摆脱 setter/getter 的自定义实现,musicPlayerCompletionBlock只声明一个属性:

typedef void(^MusicCompletionBlockType)(void);
.... 
@property(copy) MusicCompletionBlockType musicCompletionBlock;

生成的 setter/getter 将负责复制块。dealloc如果不使用 ARC,您可以在 中发布它。

于 2012-08-04T12:26:32.497 回答