NSArrayController为什么这不起作用?

时间:2012-11-01 16:27:01

标签: objective-c cocoa nsarraycontroller

我正在尝试编写一个例程,该例程从制表符分隔文件中导入数百个客户记录到NSArrayController。

这是我的初始代码:

NSString *stringFromFile = [NSString stringWithContentsOfFile:[fileURL path]
                                encoding:NSUTF8StringEncoding error:&error];
NSArray *paragraphsArray = [stringFromFile componentsSeparatedByString:@"\r"];
NSMutableDictionary *destDict = [[NSMutableDictionary alloc] init];

int i;
for (i = 0; i <= [paragraphsArray count]-1; i++) {
    NSString *currentParagraph = [paragraphsArray objectAtIndex:i];
    if ([currentParagraph length ] > 4) {
        NSArray *elementsArray = [currentParagraph componentsSeparatedByString:@"\t"];
        if ([elementsArray count] > 0) {
            currentSerial++;
            [destDict setObject:[NSString stringWithFormat:@"%ld",currentSerial]
                         forKey:@"idSerial"];
            [destDict setObject:[elementsArray objectAtIndex:1]
                         forKey:@"destRazaoSocial"];
            [destDict setObject:[elementsArray objectAtIndex:2]
                         forKey:@"destLogradouro"];
            [destDict setObject:[elementsArray objectAtIndex:3]
                         forKey:@"destLogradouroNro"];
            /// repeat this for every field...
            //Add the record:
            [destArrayController addObject:destDict];
        }
    }
}

此代码导致错误地插入记录,如果我在一个示例中有4条记录,则插入的四条记录将与最后一条记录具有相同的内容。

但是,如果我将代码更改为此,分配destDict并将其丢弃在每个循环上,它可以工作:

NSString *stringFromFile = [NSString stringWithContentsOfFile:[fileURL path]
                                   encoding:NSUTF8StringEncoding error:&error];
NSArray *paragraphsArray = [stringFromFile componentsSeparatedByString:@"\r"];
int i;
for (i = 0; i <= [paragraphsArray count]-1; i++) {
    NSString *currentParagraph = [paragraphsArray objectAtIndex:i];
    if ([currentParagraph length ] > 4) {
        NSArray *elementsArray = [currentParagraph componentsSeparatedByString:@"\t"];
        if ([elementsArray count] > 0) {
            NSMutableDictionary *destDict = [[NSMutableDictionary alloc] init];
            currentSerial++;
            [destDict setObject:[NSString stringWithFormat:@"%ld",currentSerial]
                         forKey:@"idSerial"];
            [destDict setObject:[elementsArray objectAtIndex:1]
                         forKey:@"destRazaoSocial"];
            [destDict setObject:[elementsArray objectAtIndex:2]
                         forKey:@"destLogradouro"];
            [destDict setObject:[elementsArray objectAtIndex:3]
                         forKey:@"destLogradouroNro"];
            /// repeat this for every field...
            //Add the record:
            [destArrayController addObject:destDict];
            [destDict release];
        }
    }
}

这很有效,但对我来说并不优雅。 你能这么好地告诉我这样做的正确方法吗?

2 个答案:

答案 0 :(得分:1)

以你发布的第二种方式做这件事并没有错。另一种方法(可能会或可能不会更好)是第一种方式,但将[destDict copy]而不是destDict添加到您的数组。

关于你的for循环的另一点 - 如果你不需要使用你的代码中没有的索引,你应该使用快速枚举。它写得更快更容易。所以,这个:

int i;
for (i = 0; i <= [paragraphsArray count]-1; i++) {
    NSString *currentParagraph = [paragraphsArray objectAtIndex:i];

可以这样做(称为for-in循环):

for (NSString *currentParagraph in paragraphArray){
    ....
    ....
}

答案 1 :(得分:1)

第一个代码不起作用的原因是您在循环外部创建NSMutableDictionary,更改其内容,然后将其多次添加到数组中。

将对象添加到数组时,它不会创建对象的实际副本,而是会向该对象发送retain消息。因此,在您的第一个代码段中,因为您在循环之外创建了destDict实例,所以最终会多次向该数组添加相同的destDict实例。因为它是相同的实例,所以字典将有效地包含您在最后一个循环中所做的更改的内容。

您可以使用第二个示例中的代码,但不是使用destDict创建alloc/init,而只需使用[NSMutableDictionary dictionary]创建自动发布的实例。然后,在将其添加到阵列控制器后,无需添加[destDict release];行。 (不是很重要,但无论如何)......

NSString *stringFromFile = [NSString stringWithContentsOfFile:[fileURL path]
                                encoding:NSUTF8StringEncoding error:&error];
NSArray *paragraphsArray = [stringFromFile componentsSeparatedByString:@"\r"];
int i;
for (i = 0; i <= [paragraphsArray count]-1; i++) {
    NSString *currentParagraph = [paragraphsArray objectAtIndex:i];
    if ([currentParagraph length ] > 4) {
        NSArray *elementsArray = [currentParagraph componentsSeparatedByString:@"\t"];
        if ([elementsArray count] > 0) {

            NSMutableDictionary *destDict = [NSMutableDictionary dictionary];

            currentSerial++;
            [destDict setObject:[NSString stringWithFormat:@"%ld",currentSerial]
                         forKey:@"idSerial"];
            [destDict setObject:[elementsArray objectAtIndex:1]
                         forKey:@"destRazaoSocial"];
            [destDict setObject:[elementsArray objectAtIndex:2]
                         forKey:@"destLogradouro"];
            [destDict setObject:[elementsArray objectAtIndex:3]
                         forKey:@"destLogradouroNro"];
            /// repeat this for every field...
            //Add the record:
            [destArrayController addObject:destDict];
        }
    }
}