首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NSMutableSet时出错

使用NSMutableSet时出错
EN

Stack Overflow用户
提问于 2011-10-27 21:03:30
回答 6查看 2.3K关注 0票数 1

我知道错误了

*终止应用程序由于非正常异常'NSGenericException',原因:'* Collection <__NSCFSet: 0x6b66390>在被枚举时发生了变异。‘

在我的类中添加新的委托时。或者至少,这就是我认为的问题所在。

这是我的代码: MyAppAPI.m

代码语言:javascript
复制
[...]
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];
}
[...]

@end

MyAppAPI是一个单例,我可以在整个应用程序中使用它。无论我能做什么(或者应该做什么):[MyAppAPI addDelegate:self]

这很好,但只在第一个视图中。该视图有一个带有UIScrollView的PageViewController,它在其内部加载新的视图。这些新视图注册到MyAppAPI,以侦听消息,直到它们被卸载(在这种情况下,它们会执行removeDelegate)。然而,在我看来,在UIScrollView的第二个视图上做了一个UIScrollView之后,它就直接消失了。

我怎样才能改进代码以避免这种情况发生呢?

更新

我想进一步澄清一下。所发生的事情是视图控制器"StartPage“有一个带有页面控制器的UIScrollView。它加载其他几个视图(在当前可见屏幕的前面1个)。每个视图都是一个instans PageViewController,它使用上面显示的addDelegate函数将自己注册到名为MyAppAPI的全局单例中。但是,正如我所理解的,当viewcontroller 2注册自己时,这个viewcontroller 1仍然在从委托读取,因此错误显示在上面。

我希望我已经说清楚了。我试过几件事,但没有任何帮助。即使在读取委托时,我也需要使用addDelegate向委托注册。我该怎么做?

更新2这是响应方法之一:

代码语言:javascript
复制
+ (void)didRecieveFeaturedItems:(NSArray*)items
{   
    for (id delegate in _delegates)
    {
        if ([delegate respondsToSelector:@selector(didRecieveFeaturedItems:)])
            [delegate didRecieveFeaturedItems:items];
    }
}
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-11-02 00:56:12

斯科特·亨特是对的。当您在迭代时尝试编辑列表时,会引发此错误。

下面是一个例子,说明你可能在做什么。

代码语言:javascript
复制
+ (void)iteratingToRemove:(NSArray*)items {   
    for (id delegate in _delegates) {
        if(delegate.removeMePlease) {
          [MyAppAPI removeDelegate:delegate];  //error you are editing an NSSet while enumerating
        }
    }
}

下面是您应该如何正确地处理这个问题:

代码语言:javascript
复制
+ (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];
}
票数 11
EN

Stack Overflow用户

发布于 2011-10-27 21:12:46

该错误表明,当某些代码处于浏览列表的中间时,您正在修改列表(这说明了调用addDelegate后的崩溃)。如果执行枚举的代码是修改列表的代码,那么您只需将修改推迟到枚举完成(例如,通过在另一个列表中收集它们)。如果不了解执行枚举的代码,就不能说得更多了。

票数 5
EN

Stack Overflow用户

发布于 2011-11-07 11:58:03

一个简单的解决方案,不要使用可变的集合。由于各种原因,包括这个原因,它们是危险的。

您可以使用-copy和-mutableCopy在NSSet (和许多其他类)的可变版本和非可变版本之间进行转换。小心所有复制方法返回一个保留计数为1的新对象(就像alloc一样),所以您需要释放它们。

除了有较少的潜在错误,非可变对象更快地使用和使用较少的内存。

代码语言:javascript
复制
[...]
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];
}
[...]

@end
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7922386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档