Objective-C高效闭环等效的NSMutableArray

时间:2011-11-19 18:07:01

标签: objective-c data-structures nsmutablearray ios5 iphone-4

现在我的应用程序使用预先分配的约40000个对象的NSMutableArray。当应用程序达到此限制时,它会因索引超出范围异常而崩溃。我想通过重新使用较小阵列中的对象来消除这种担忧,比方说900项。这应该给我足够的空间,以便能够在特定时间窗口内查询先前的对象。

我正在努力避免不断增长数组,我看到了两个可能的解决方案(我使用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 个答案:

答案 0 :(得分:2)

我会使用circular buffer,这类似于你对#2的建议。

我认为你的#1方法可能更简单,但可能太慢了,因为当你修改数组的头部时,数组可能会做很多工作。观察你的出队方法;它需要保留并自动释放返回的对象,然后才能将其从队列中删除。

答案 1 :(得分:0)

我认为您可以简单地使用数组计数的模数:

array[index%array.count];

答案 2 :(得分:0)

在NSMutableArray中,在开头和结尾添加/删除元素都是 fast (几十纳秒)。没有必要实现一个奇特的循环缓冲区,因为NSMutableArray本身就很聪明。只需在末尾添加元素并在开始时删除它们。