2012-11-01 172 views
1

我正在嘗試編寫一個從製表符分隔的文件導入數百個客戶記錄到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個記錄的例子中,四個記錄插入將具有相同內容的最後一個記錄。

但是,如果我的代碼改變這一點,allocing 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]; 
     } 
    } 
} 

這工作,但它看起來並不優雅給我。 您是否真的好好告訴我這樣做的正確方法?

回答

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

之所以第一個代碼不工作就是要創建的NSMutableDictionary外循環,更改其內容,然後將其多次添加到數組中。

將對象添加到數組時,它不會創建對象的實際副本,而是僅向該對象發送消息retain。因此,在您的第一個代碼段中,因爲您在循環外部創建了destDict實例,所以最終將同一個destDict實例添加到該陣列多次。由於它是相同的實例,因此字典將有效地包含您在最後一個循環中所做更改的內容。

您可以使用類似的代碼在你的第二個例子,但不是使用alloc/init創建destDict,使用[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]; 
     } 
    } 
}