Pad*_*215 1 cocoa-touch objective-c ios
我有一个充满按钮的UIView*buttonView.我需要更新我的列表并重新填充我的buttonView.我实施了:
if ([[self.buttonView.subviews objectAtIndex:i] isKindOfClass:[UIButon class]]
[[self.buttonView.subviews objectAtIndex:i] removeFromSuperview];
Run Code Online (Sandbox Code Playgroud)
但它失败了,它不会删除所有的按钮(我的测试有8个按钮,它删除了每个其他按钮: - ?)
然后我尝试了:
for(UIView *subview in self.buttonView.subviews)
{
if([subview isKindOfClass:[UIButton class]])
[subview removeFromSuperview];
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好.
两个循环不应该完成同样的事情吗?
我猜有些东西我不知道快速枚举可以解释这个吗?
你的根本问题是你在迭代时改变了一个集合.如果您确实需要这样做,您可能需要考虑向后迭代(使用-reverseObjectEnumerator或使用-enumerateObjectsWithOptions:usingBlock:反向选项).或者,您可以在迭代之前创建数组的副本.
快速枚举工作的原因可能是由于调用-subviews返回子视图数组的某种常量副本.这实际上可以在你的第一种情况下使用,只需调用-subviews一次并重新使用结果,但这会引入对实现细节的依赖,我强烈建议避免它.如果你需要一个数组的常量副本,你应该自己制作一个.
解决案例1的最快解决方案是:
NSArray *subviews = [NSArray arrayWithArray:self.buttonView.subviews];
// now enumerate using the subviews array directly instead of calling self.buttonView.subviews
Run Code Online (Sandbox Code Playgroud)
对于快速枚举的情况,您可能希望将其重写为
for (UIView *subview in [NSArray arrayWithArray:self.buttonView.subviews]) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
第三种选择是切换到基于块的枚举并反向进行.如果你能做到这一点,这实际上将是最有效的选择:
[self.buttonView.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
if ([subview isKindOfClass:[UIButton class]]) {
[subview removeFromSuperview];
}
}];
Run Code Online (Sandbox Code Playgroud)