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

セッターでブロックをコピーする必要があります。ブロックはスタックから始まり、コピーされるまでヒープに移動しません。

オプティマイザが有効になっていないため、デバッグビルドで「機能」します。したがって、コンパイラはスタックを積極的に再利用しません。つまり、偶然に機能します。ブロックの作成と呼び出しの間にメソッド呼び出しを1つか2つ追加すると、クラッシュし始める可能性があります。

のsetter/getterのカスタム実装を取り除きmusicPlayerCompletionBlock、プロパティを宣言することをお勧めします。

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

生成されたセッター/ゲッターがブロックのコピーを処理します。deallocARCを使用していない場合は、でリリースできます。

于 2012-08-04T12:26:32.497 に答える