Objective-C эффективный эквивалент замкнутого цикла NSMutableArray - PullRequest
0 голосов
/ 19 ноября 2011

Прямо сейчас мое приложение использует предварительно выделенный NSMutableArray из ~ 40000 объектов. Когда приложение достигает этого предела, оно падает из-за исключения индекса за пределами границ. Я хотел бы устранить эту проблему, повторно используя объекты в меньшем массиве, скажем, 900 элементов. Это должно дать мне достаточно места, чтобы иметь возможность запрашивать предыдущие объекты в течение определенного промежутка времени.

Я пытаюсь избежать непрерывного увеличения массива и вижу 2 возможных решения (я использую ARC и backgroundSelector для периодического автоматического сохранения данных):

1) продолжайте удалять старые объекты, когда новые будут вставлены. Я вижу потенциальную обратную сторону необходимости постоянно распределять объекты. Преимущество состоит в том, что данные в порядке, и я контролирую количество элементов в массиве, доступ к элементам также прост. Некоторая логика приложения может сломаться, если я попытаюсь получить доступ к элементу, который находится за пределами цикла (например, очередь из 900 элементов, и я пытаюсь получить доступ к элементу (currentIndex -1200). Другой недостаток заключается в том, что это не безопасное использование с несколькими потоками, если я попытаюсь перебрать массив, чтобы попытаться сохранить некоторые элементы, произойдет сбой, если я попытаюсь удалить этот же массив из другого потока.

NSMutableArray* queue;


- (NSNumber*) dequeue:(NSMutableArray*)queue {
    if ([queue count] == 0) return nil; // to avoid raising exception (Quinn)
    id headObject = [queue objectAtIndex:0];
    if (headObject != nil) {
        // so it isn't dealloc'ed on remove
        [queue removeObjectAtIndex:0];
    }
    return headObject;
}

// Add to the tail of the queue (no one likes it when people cut in line!)
- (void) enqueue:(NSNumber*)anObject forQueue:(NSMutableArray*) queue{
    [queue addObject:anObject];
    //this method automatically adds to the end of the array
}

2) Используйте замкнутый контур и сбрасывайте объекты перед использованием. Здесь любая логика доступа к массиву все еще будет работать, хотя результаты могут быть удивительными. Я также не проверял ни один из этих методов.

NSMutableArray loopingArray;

- (id) getObjectAtIndex:(int)arrayIndex{
    id object =  [loopingArray objectAtIndex:arrayIndex %arraySize];  
    return object;
}

- (id) getObjectForWriting{
    [loopingArray resetForEvent:(++currentIndex %arraySize)];  
    id object =  [loopingArray objectAtIndex:currentIndex %arraySize];  
    return object;
}

- (id) getCurrentObject{
    id object =  [loopingArray objectAtIndex:currentIndex %arraySize];  
    return object;
}

-(void)resetForEvent:(int)event
{
   //get an object at index and ask it to reset itself 
}

3) То же, что и очередь, за исключением того, что объект в очереди сбрасывается и вставляется в начало очереди. Это кажется самым разумным решением.

Как бы вы решили такую ​​проблему? После этого кажется, что очередь - более простое решение, даже если для этого потребуется перераспределение объектов.

Обновлено: В итоге я использовал кольцевой буфер, подобный структуре данных:

int count = [mutableArray count]
    [mutableArray replaceObjectAtIndex:((lastProcessedEpoch+1)%count) withObject:newDataPoint];
    lastProcessedEpoch++;

Все последующие обращения к массиву используют текущий индекс% count. Вызов на замену можно изменить на сброс, но я не хочу писать метод сброса для ~ 30 переменных в точке данных.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 19 ноября 2011

Я бы использовал циклический буфер , который похож на то, что вы предлагаете для # 2.

Я думаю, что ваш метод # 1, вероятно, проще, хотя может бытьслишком медленно, так как массив может выполнять большую работу при изменении заголовка массива.Следите за своим методом dequeue;перед удалением его из очереди необходимо сохранить и автоматически освободить возвращенный объект.

0 голосов
/ 23 марта 2014

В NSMutableArray добавление / удаление элементов как в начале, так и в конце: fast (десятки наносекунд). Нет необходимости реализовывать причудливый циклический буфер, потому что NSMutableArray сам по себе умен. Просто добавьте элементы в конце и удалите их в начале.

0 голосов
/ 27 ноября 2013

Я думаю, что вы можете просто использовать модуль массива:

array[index%array.count];
...