2009-08-21 15 views
6

我正在爲一個相當複雜的表實現一個自定義的searchBar,並且再次遇到了這種代碼模式。這從一開始就iPhone開發的書樣本:快速枚舉(循環)在Objective-C中如何工作? (即:for(NSString * aString in a Dictionary))

- (void)handleSearchForTerm:(NSString *)searchTerm 
{ 
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init]; 
[self resetSearch]; 

for (NSString *key in self.keys) 
    { 
    NSMutableArray *array = [self.names valueForKey:key]; 
    NSMutableArray *toRemove = [[NSMutableArray alloc] init]; 
    for (NSString *name in array) 
    { 
     if ([name rangeOfString:searchTerm 
         options:NSCaseInsensitiveSearch].location == NSNotFound) 
      [toRemove addObject:name]; 
    } 

    if ([array count] == [toRemove count]) 
     [sectionsToRemove addObject:key]; 
    [array removeObjectsInArray:toRemove]; 
    [toRemove release]; 
    } 
[self.keys removeObjectsInArray:sectionsToRemove]; 
[sectionsToRemove release]; 
[table reloadData]; 
} 

我很好奇的部分是參考「(的NSString *數組名)」。這是幹什麼的?它似乎爲數組中的每個項目創建一個字符串。另外,這是如何與字典工作?

謝謝!

+0

感謝大家的快速反應!我編輯標題以包含「快速枚舉」。 – Jonah 2009-08-21 20:50:29

回答

15

此構造是運行在Objective-C集合中的項目上的另一種for循環,而不是C數組。第一部分定義了一個對象,該對象在循環的每次運行中都被設置爲集合中的一個元素,而第二部分是要枚舉的集合。例如,代碼:

NSArray *array = [NSArray arrayWithObjects:@"foo", @"bar", nil]; 
for(NSString *string in array) { 
    NSLog(string); 
}

將打印:

foo 
bar

它定義的是,循環的每次運行,被設置在NSArray *array的下一個對象的NSString *string。類似的,你可以使用NSSet實例(其中未定義對象的順序)和NSDictionary(它將枚舉存儲在字典中的鍵上枚舉 - 你可以通過列舉枚舉鍵來枚舉值,然後使用該鍵在字典上調用valueForKey:)。

它非常類似於C的結構:

int array[2] = { 0, 1 }; 
for(int i = 0; i < 2; i++) { 
    printf("%d\n", array[i]); 
}

它打印:

0 
1

這使代碼更具可讀性和隱藏一些花哨的枚舉去的僅僅是語法的方法列入NSArray,NSSet或NSDictionary中的列表對象。 Objective-C 2.0編程語言文檔的Fast Enumeration部分給出了更多細節。

2

這是一個for循環,每個鍵在字典中都有一次迭代。

for..in結構被稱爲快速枚舉。您可以在Objective-C 2.0 Programming Guide中閱讀更多關於它的內容。

它如何與對象一起工作取決於它的NSFastEnumeration協議的實現。 NSDictionary class reference描述了它如何與字典一起工作:

在Mac OS X v10.5及更高版本上,NSDictionary支持NSFastEnumeration協議。您可以使用for ... in構造來枚舉字典的鍵,如以下示例所示。

3

這就是所謂的快速枚舉。它循環遍歷數組,將key設置爲每個項目。這是一樣的功能,因爲這樣做:

NSString *key; 
for (NSInteger i = 0; i < [[ self keys ] count ]; i++) { 
    key = [[ self keys ] objectAtIndex:i ]; 

    NSMutableArray *array = [self.names valueForKey:key]; 
    NSMutableArray *toRemove = [[NSMutableArray alloc] init]; 
    for (NSString *name in array) 
    { 
      if ([name rangeOfString:searchTerm 
        options:NSCaseInsensitiveSearch].location == NSNotFound) 
        [toRemove addObject:name]; 
    } 

    if ([array count] == [toRemove count]) 
      [sectionsToRemove addObject:key]; 
    [array removeObjectsInArray:toRemove]; 
    [toRemove release]; 
}