plist to array“集合在被枚举时被突变”异常

时间:2011-09-15 13:38:52

标签: iphone objective-c ios xcode

  

可能重复:
  Getting exception as “Collection was mutated while being enumerated”

此问题是我之前发布的另一个问题的延续How to read in plist data into a data model? @ devdavid帮助我做到这一点......

我有一个名为“HotelList.plist”的plist文件,它看起来像这样:

<array>
    <dict>
        <key>hotelID</key>
        <integer>0</integer>
        <key>name</key>
        <string>Solmar</string>
        // ... more keys and strings ...
    </dict>
    // ... more hotel entries ...
</array>

我有一个描述钥匙的“酒店”课程。 我有一个数据模型类,我想在这个plist中读到一个数组。

#import "DataModel.h"
#import "Hotel.h"

// Private methods
@interface DataModel ()

@property (nonatomic, retain) NSMutableArray *hotels;

-(void)loadHotels;

@end

@implementation DataModel

@synthesize hotels;

- (id)init {
    if ((self = [super init])) {
        [self loadHotels];
    }
    return self;
}

- (void)dealloc {
    [hotels release];
    [super dealloc];
}

- (void)loadHotels {

    NSBundle* bundle = [NSBundle mainBundle];
    NSString* plistpath = [bundle pathForResource:@"HotelList" ofType:@"plist"];

    hotels = [[NSMutableArray arrayWithContentsOfFile:plistpath]retain];

    for (NSDictionary *hotelDict in hotels) {
        Hotel *hotel = [[Hotel alloc] init];
        hotel.hotelID = [[hotelDict objectForKey:@"hotelID"] intValue];
        hotel.name = [hotelDict objectForKey:@"name"];
        [hotels addObject:hotel];
        [hotel release];
    }
}

@end

当我运行时,调试器向我显示每个酒店字典都被读入但是当它到达plist的末尾(我有大约30家酒店)时,它会尝试回到第一个并且崩溃,给出一个例外情况“收集在被枚举时发生变异”。

绿色SIGABRT指示停在

for (NSDictionary *hotelDict in hotels) {

线。我的for循环有问题吗?我设置数组/字典的方式?或者也许plist的格式是错误的(虽然我不这么认为,因为调试器显示我正在正确读取它)?

为了完整起见,我应该提一下,是的,plist文件存在且位于mainBundle中,拼写正确。此外,plist中的数据是静态的 - 我不必为文件保存任何新内容。

请帮忙!

2 个答案:

答案 0 :(得分:2)

使用访问者,而不是直接使用ivars。你的问题会更加明显,你可以避免在hotel的分配中可能发生的泄漏(如果第二次调用loadHotels)。您的代码将字典读入数组,然后尝试将Hotel个对象附加到同一个数组中。这就是你真正要说的话:

NSArray *hotelDicts = [[NSArray alloc] initWithContentsOfFile:plistpath];
self.hotels = [NSMutableArray array];

for (NSDictionary *hotelDict in hotelDicts) {
    Hotel *hotel = [[Hotel alloc] init];
    hotel.hotelID = [[hotelDict objectForKey:@"hotelID"] intValue];
    hotel.name = [hotelDict objectForKey:@"name"];
    [self.hotels addObject:hotel];
    [hotel release];
}
[hotelDicts release];

答案 1 :(得分:1)

您正在尝试修改您正在枚举的集合 - 您无法执行此操作。而不是使用枚举器,尝试迭代集合。当您遍历数组时,您仍然可以添加/删除数组成员,因为您没有绑定在开始 for block 之前定义的枚举。

迭代集合的一种方法是使用简单的for循环:

for( int i = 0; i < [array count]; i++ )
{
    id object = [array objectAtIndex:i];
    // do something with object
}