Прямо сейчас мое приложение использует предварительно выделенный 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 переменных в точке данных.
Спасибо!