1

私のアプリでは、音声分析を行っています。毎秒、次のようないくつかのメソッドを呼び出しています。

- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
    int countArray = [array count];

    if(!countArray)
        return nil;

    else if (countArray <= 5 )
        return [array valueForKeyPath:@"@avg.doubleValue"];

    else
    {
        // Création et initialisation d'un tableau temporaire
        NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:array];
        NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
        [averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];


        for (int j = 0; j < countArray / 3; j++)
        {
            [averageArray removeLastObject];
            [averageArray removeObjectAtIndex:0];
        }


        NSNumber * average = [averageArray valueForKeyPath:@"@avg.doubleValue"];


        return average;
        }

}

問題は、配列インデックスが境界を超えていることを示す NSRangeException エラー (1 分後または数時間後...場合によって異なります...) を受け取ることがあることです。奇妙なことは、インデックスが範囲外ではないことです...これらのメソッドはメインスレッドでのみ呼び出されます。よろしくお願いいたします。

編集 1: Anim と Abhinav の助けを借りて、コードを次のように変更しました。2 時間 45 分 (これは記録です) 以上動作し、その後 EXC_BAD_ACCESS コード 1 エラーでクラッシュします...

- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
    NSArray *arrayCopy = [[NSArray alloc] initWithArray:array]; // CRASH with EXC_BAD_ACCESS error

    int countArray = [arrayCopy count];

    if(!countArray)
        return nil;

    else if (countArray <= 5 )
        return [arrayCopy valueForKeyPath:@"@avg.doubleValue"];

    else
    {
        // Création et initialisation d'un tableau temporaire
        NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:arrayCopy];
        NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
        [averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];

        int startOfRange = countArray / 3;
        int rangeLength = countArray - 2 * (countArray / 3);

        NSArray* slicedArray = [averageArray subarrayWithRange:NSMakeRange(startOfRange, rangeLength)];

        NSNumber * average = [slicedArray valueForKeyPath:@"@avg.doubleValue"];

        return average;
    }

}
4

2 に答える 2

2

与えられたコードでは、ここで何が起こっているのかを推測することになります。次のことを確認してください。

  1. 「removeLastObject」または「removeObjectAtIndex」を呼び出す前に、配列カウントをチェックすることは理にかなっています。削除するものがある場合にのみ呼び出します。
  2. NSArray と NSMutableArray はスレッドセーフではないため、操作している配列が変更されたり、同時に使用されたりしないようにしてください。

For ループ内に次のステートメントを挿入したいと思います。

if (averageArray.count > 0) {
    [averageArray removeLastObject];
}

if (averageArray.count > 0) {
    [averageArray removeObjectAtIndex:0];
}
于 2013-10-20T16:55:03.837 に答える
0

ループの前に 1 つの条件を追加するだけで、もう 1 つ実行できます。これがスニペットで、コメントが追加されています。

- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
    int countArray = [array count];

    if(!countArray)
        return nil;

    else if (countArray <= 5 )
        return [array valueForKeyPath:@"@avg.doubleValue"];

    else
    {
        // Création et initialisation d'un tableau temporaire
        NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:array];
        NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
        [averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];

       if ([array count] > 0)  //Added one condition here---PR Singh
      { 
          for (int j = 0; j < countArray / 3; j++)
          {
             [averageArray removeLastObject];
             [averageArray removeObjectAtIndex:0];
          }
      }


        NSNumber * average = [averageArray valueForKeyPath:@"@avg.doubleValue"];


        return average;
        }

}
于 2013-10-21T06:54:55.130 に答える