2012-08-04 92 views
3

我有一个问题,我现在还没有能够解决的问题,它只发生在发布版本中,我没有任何问题,当我在调试版本中运行它时。发布版本上的块崩溃

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

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的方法:成功是这样的:

- (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); 
+0

你在哪里定义块,以及如何存储它?另外,你使用的是ARC吗? – 2012-08-04 11:08:50

+0

该块在另一个对象中定义,如下所示: [[NOAudioManager sharedManager] setMusicCompletionBlock:^ {self videoDidFinish]; }]; 是的,我正在使用ARC。 音频播放完毕。该应用程序在发布版本中崩溃。 – WYS 2012-08-04 12:08:58

+0

请编辑原始问题以包含正确格式化的信息。这将有助于澄清未来读者的问题,并且在评论中非常难以阅读。 – 2012-08-04 12:38:46

回答

8

你需要在你的setter中复制这个块。块开始在堆栈上,并且不会移动到堆上直到被复制。

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

我建议你摆脱的setter /吸气剂为musicPlayerCompletionBlock定制实现的,只是声明一个属性:

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

生成的setter /吸气将采取复制块的照顾。如果不使用ARC,您可以在dealloc中释放它。

+0

Omfg解决了我的问题!非常感谢,你救了我的一天!也许有人可以解释为什么这在调试模式下工作,而不是释放? – WYS 2012-08-04 13:45:47

相关问题