我知道错误了
*终止应用程序由于非正常异常'NSGenericException',原因:'* Collection <__NSCFSet: 0x6b66390>在被枚举时发生了变异。‘
在我的类中添加新的委托时。或者至少,这就是我认为的问题所在。
这是我的代码: MyAppAPI.m
[...]
static NSMutableSet *_delegates = nil;
@implementation MyAppAPI
+ (void)initialize
{
if (self == [MyAppAPI class]) {
_delegates = [[NSMutableSet alloc] init];
}
}
+ (void)addDelegate:(id)delegate
{
[_delegates addObject:delegate];
}
+ (void)removeDelegate:(id)delegate
{
[_delegates removeObject:delegate];
}
[...]
@endMyAppAPI是一个单例,我可以在整个应用程序中使用它。无论我能做什么(或者应该做什么):[MyAppAPI addDelegate:self]。
这很好,但只在第一个视图中。该视图有一个带有UIScrollView的PageViewController,它在其内部加载新的视图。这些新视图注册到MyAppAPI,以侦听消息,直到它们被卸载(在这种情况下,它们会执行removeDelegate)。然而,在我看来,在UIScrollView的第二个视图上做了一个UIScrollView之后,它就直接消失了。
我怎样才能改进代码以避免这种情况发生呢?
更新
我想进一步澄清一下。所发生的事情是视图控制器"StartPage“有一个带有页面控制器的UIScrollView。它加载其他几个视图(在当前可见屏幕的前面1个)。每个视图都是一个instans PageViewController,它使用上面显示的addDelegate函数将自己注册到名为MyAppAPI的全局单例中。但是,正如我所理解的,当viewcontroller 2注册自己时,这个viewcontroller 1仍然在从委托读取,因此错误显示在上面。
我希望我已经说清楚了。我试过几件事,但没有任何帮助。即使在读取委托时,我也需要使用addDelegate向委托注册。我该怎么做?
更新2这是响应方法之一:
+ (void)didRecieveFeaturedItems:(NSArray*)items
{
for (id delegate in _delegates)
{
if ([delegate respondsToSelector:@selector(didRecieveFeaturedItems:)])
[delegate didRecieveFeaturedItems:items];
}
}发布于 2011-11-02 00:56:12
斯科特·亨特是对的。当您在迭代时尝试编辑列表时,会引发此错误。
下面是一个例子,说明你可能在做什么。
+ (void)iteratingToRemove:(NSArray*)items {
for (id delegate in _delegates) {
if(delegate.removeMePlease) {
[MyAppAPI removeDelegate:delegate]; //error you are editing an NSSet while enumerating
}
}
}下面是您应该如何正确地处理这个问题:
+ (void)iteratingToRemove:(NSArray*)items
{
NSMutableArray *delegatesToRemove = [[NSMutableArray alloc] init];
for (id delegate in _delegates) {
if(delegate.removeMePlease) {
[delegatesToRemove addObject:delegate];
}
}
for(id delegate in delegatesToRemove) {
[MyAppAPI removeDelegate:delegate]; //This works better
}
[delegatesToRemove release];
}发布于 2011-10-27 21:12:46
该错误表明,当某些代码处于浏览列表的中间时,您正在修改列表(这说明了调用addDelegate后的崩溃)。如果执行枚举的代码是修改列表的代码,那么您只需将修改推迟到枚举完成(例如,通过在另一个列表中收集它们)。如果不了解执行枚举的代码,就不能说得更多了。
发布于 2011-11-07 11:58:03
一个简单的解决方案,不要使用可变的集合。由于各种原因,包括这个原因,它们是危险的。
您可以使用-copy和-mutableCopy在NSSet (和许多其他类)的可变版本和非可变版本之间进行转换。小心所有复制方法返回一个保留计数为1的新对象(就像alloc一样),所以您需要释放它们。
除了有较少的潜在错误,非可变对象更快地使用和使用较少的内存。
[...]
static NSSet *_delegates = nil;
@implementation MyAppAPI
+ (void)initialize
{
if (self == [MyAppAPI class]) {
_delegates = [[NSSet alloc] init];
}
}
+ (void)addDelegate:(id)delegate
{
NSMutableSet *delegatesMutable = [_delegates mutableCopy];
[delegatesMutable addObject:delegate];
[_delegates autorelease];
_delegates = [delegatesMutable copy];
[delegatesMutable release];
}
+ (void)removeDelegate:(id)delegate
{
NSMutableSet *delegatesMutable = [_delegates mutableCopy];
[delegatesMutable removeObject:delegate];
[_delegates autorelease];
_delegates = [delegatesMutable copy];
[delegatesMutable release];
}
[...]
@endhttps://stackoverflow.com/questions/7922386
复制相似问题