我在一个旧的Objective-C应用程序中有一个数组,我用它来学习更多"复杂"编码。它是从OS X的旧时代回来的,并且非常破碎。我已经让它工作(大多数)!但是,该应用程序有一个NSMutableArray图像,总共7个。我使用随机数生成器在屏幕上插入图像,一些代码允许它们下降,然后,使用屏幕边界,当它们到达" 0"在Y轴上,它们将从阵列中移除。 我最初只是:
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
[flakesArray removeObject:myItem];
我从数组中删除对象时已经读过,最好反过来迭代...所以我有这段代码:
for (NSInteger i = myArray.count - 1; i >= 0; i--)
{ //added for for statement
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
[myArray removeObjectAtIndex:i];
}
可悲的是,这两种方法都会在枚举错误时导致相同的变异。我错过了一些明显的东西吗 如果我添加一个NSLog语句,我认为我可以得到需要删除的项目的索引:
NSLog (@"Shazam! %ld", (long)i);
2017-01-07 14:39:42.086667 MyApp [45995:7500033] Shazam! 2
我已经仔细研究过并尝试了几种不同的方法,包括这个one,它看起来是最受欢迎的同一错误。
提前谢谢!我很乐意提供任何其他信息!
添加更多: 对不起伙计我没有明确地调用NSFastEnumeration,但我有这个:
- (void) drawRectCocoa:(NSRect)rect
{
NSEnumerator* flakesEnum = [flakesArray objectEnumerator];
然后
for( i = 0; i < numberToCreate; i++ )
{
[self newObject:self];
}
while( oneFlake = [flakesEnum nextObject] )
在这里:
if( currentFrame.origin.y+currentFrame.size.height <= 0 )
{
NSLog (@"Shazam! %i", oneFlake);
[flakesArray removeObject:oneFlake];
}
谢谢大家。我从这次讨论中学到了很多东西!
答案 0 :(得分:3)
有两种方法:(1)收集要删除的对象,然后使用removeObjectsInArray:将其删除。
<html>
<head>
<link rel=StyleSheet href="/static/style.css" type="text/css" media="screen">
</head>
<body>
<div id="content">
{{ tweet }}
</div>
</body>
</html>
或者,NSMutableArray *removeThese = [NSMutableArray array];
for (id item in myArray) {
if (/* item satisfies some condition for removal */) {
[removeThese addObject:item];
}
}
// the following (and any other method that mutates the array) must be done
// *outside of* the loop that enumerates the array
[myArray removeObjectsInArray:removeThese];
可以容忍在迭代期间删除...
reverseObjectEnumeration
答案 1 :(得分:2)
根据错误,当任何foreach (Control control in this.Controls)
{
if (control is PictureBox)
{
this.Controls.Remove(control);
}
}
(或任何NSMutableArray
集合)被枚举为任何快速枚举循环(NSMutable...
)的一部分时,您可能不会改变它。
@ danh的答案也有效,但涉及分配新的元素数组。有两种更简单,更有效的方法来过滤数组:
for (... in ...) { ... }
或
[array filterUsingPredicate:[NSPredicate predicateWithBlock:^(id element, NSDictionary<NSString *,id> *bindings) {
// if element should stay, return YES; if it should be removed, return NO
}];
filterUsingPredicate:
可能稍快一些(因为它本身使用快速枚举),但根据具体应用,removeObjectsAtIndexes:
可能更灵活。
无论如何,如果你在快速枚举循环中使用你的数组,你将不得不在循环之外执行修改。您可以使用NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet new];
for (NSUInteger i = 0; i < array.count; i += 1) {
if (/* array[i] should be removed */) {
[indicesToRemove addIndex:i];
}
}
[array removeObjectsAtIndexes:indicesToRemove];
完全替换循环,也可以保持循环并跟踪要删除的元素的索引以供日后使用。