0

私のアプリでは、オーディオ処理を行っています。オーディオ バッファの for ループには、NSMutable 配列があります。ループは毎秒膨大な回数呼び出されます (バッファ サイズによって異なります)。例として:

@autoreleasepool
{
    for ( int i = 0; i < tempBuffer.mDataByteSize / 2; ++i )
    {
        if ( samples[i] > trig)
        {
            [self.k_Array addObject:[NSNumber numberWithInt:k]];

            // other stuff

        }
    }
}

その後、毎秒、他の処理のために関数を呼び出しています。

- (void)realtimeUpdate:(NSTimer*)theTimer
{
// Create a copy of the array
NSMutableArray *k_ArrayCopy = [NSMutableArray arrayWithArray:k_Array]; // CRASH with EXC_BAD_ACCESS code 1 error

//do some stuff with k_ArrayCopy
}

配列のロックの問題が原因で、EXC_BAD_ACCESS エラーが発生することがあります。キュー、ロック、作業コピーなどに関する情報を取得するために多くの時間を費やしました...しかし、この特定のケースについてはわかりません。私の質問:

  1. にアトミックまたは非アトミックを使用する必要がありk_arrayますか?
  2. dispatch_sync関数を使用する必要がありますか? もしそうなら、正確にはどこですか?
  3. realtimeUpdate関数をバックグラウンドで呼び出す必要がありますか?

前もって感謝します !

4

1 に答える 1

0

問題を解決するディスパッチ キューを使用する

//キューインスタンス変数を作成

dispatch_queue_t q = dispatch_queue_create("com.safearrayaccess.samplequeue", NULL);

//1.

 @autoreleasepool
    {
        for ( int i = 0; i < tempBuffer.mDataByteSize / 2; ++i )
        {
            if ( samples[i] > trig)
            {
               dispatch_async(q, ^{ 
                //queue block
                [self.k_Array addObject:[NSNumber numberWithInt:k]];

                });

                // other stuff NOTE: if its operation on array do it in queue block only

            }
        }
    }

//2.

 - (void)realtimeUpdate:(NSTimer*)theTimer
  {
    // Create a copy of the array
    __block NSMutableArray *k_ArrayCopy;//when you use any variable inside block add __block before it

    dispatch_async(q, ^{
            //queue block
            k_ArrayCopy = [NSMutableArray arrayWithArray:k_Array]; 
        });

        //do some stuff with k_ArrayCopy
    }

これで、配列の追加操作と読み取り操作が同じキュー上にあり、競合しなくなりました。ディスパッチ キューの使用の詳細については、apples Grand Central Dispatch doc を参照してください。

これを行う他の方法は、NSConditonLock を使用することです。

于 2013-10-23T21:07:31.890 に答える