我有一个controller
,其中有一个包含actors
的数组。 actor是一个将由controller
调用的对象。
问题:controller
遍历actors
数组并向每个参与者发送-actionMessage
。 actor可以使用controller
创建和注册另一个actor,或者从控制器的actors数组中删除一个actor甚至自己。它通过两种方法传递:
-registerActor:(Actor*)actor;
-unregisterActor:(Actor*)actor;
因此,当控制器遍历actors数组时,actor的列表可以更改。 编辑:任何新添加的演员也必须经历循环。
处理此问题的最佳做法是什么?我应该在迭代之前创建一个actors数组的副本吗?
答案 0 :(得分:7)
创建可变数组的副本并迭代它。
NSArray *loopArray = [NSArray arrayWithArray: yourActorArray];
或者
NSArray *loopArray = [yourActorArray copy];
//in this case remember to release in nonARC environment
答案 1 :(得分:2)
这就是我通常做的......
NSMutableArray *discardedItems = [NSMutableArray array];
SomeObjectClass *item;
for (item in originalArrayOfItems) {
if ([item shouldBeDiscarded])
[discardedItems addObject:item];
}
[originalArrayOfItems removeObjectsInArray:discardedItems];
希望这会有所帮助。
答案 2 :(得分:2)
通过一个可变数组进行枚举的标准过程需要在逐步执行时进行更改,这是为了复制并迭代它,改变原始数据。我猜测演员的NSMutableArray是属于你的控制器的属性,而registerActor:和unregisterActor:都改变了这个数组。如果您单步执行副本,则可以通过方法从原始属性中删除actor,而无需更改副本。
NSMutableArray *actorArrayCopy = [self.actorArray copy];
for (id object in actorArrayCopy){
//do stuff
}
在某些情况下,您可以废弃快速枚举并使用标准for循环,但是,这在这里存在风险。如果从数组中插入或删除对象,索引将移位(AFAIK),这意味着您可能最终跳过元素或多次遍历元素。
有些人将要更改的元素(例如已删除)存储在快速枚举中的单独数组中,并在枚举完成后立即执行所有更改,但是您使用单独的方法来添加和删除元素;元素本身决定了应该发生什么并通知你。这会使事情变得更复杂,因此副本可能效果最好。
答案 3 :(得分:1)
您可以通过执行以下操作来避免复制数组:
for(int i=0; i<[array count]; i++)
{
if(condition)
{
[array removeObjectAtIndex:i];
i --;
continue;
}
}
答案 4 :(得分:1)
您应该使用集合而不是数组。然后你可以复制这个集合,并在完成操作后,取一个差异来看看发生了什么变化。
答案 5 :(得分:0)
我创建了一个名为smartFor
的宏,该宏可以让您进行与for循环快速枚举相同的设置,但可以处理数组的修改。它利用了一些C和CLANG漏洞,非常简单干净。
///Allows for modifying an array during virtual fast enumeration
#define smartFor(__objectDeclaration, __array, __block) {\
int __i = 0;\
while (__i < __array.count) {\
__objectDeclaration = __array[__i];\
NSObject *__object = __array[__i];\
[__block invoke];\
if ([__array indexOfObjectIdenticalTo:__object] != NSNotFound && ((int)[__array indexOfObjectIdenticalTo:__object]) <= __i) {\
__i = ((int)[__array indexOfObjectIdenticalTo:__object])+1;\
}\
}\
}
它会自动处理您可能要做的所有[基本]不可思议的事情,例如添加对象(在数组中的任何位置,在“快速枚举”中的任何时候 [1] ),删除对象,调整对象的索引,修改对象等。
smartFor(NSNumber *aNumber, myArray, ^{
if ([aNumber isEqualToNumber:@(3)]) {
[myArray removeObjectIdenticalTo:aNumber];
}
});
[1] 注意:显然,在严格的定义/性能基础上,这并不是技术上的快速枚举,但是出于所有目的和目的,其行为都与之类似
答案 6 :(得分:-2)
你应该使用普通的for循环
for ( ''initializer''; ''conditional expression''; ''loop expression'' )
{
// statements to be executed
}
不要使用fast / objective -c进行循环。它允许你编辑数组......