2013/07/04

Objective-C迭代陣列

當手上有一堆東西時,常常就會需要作「迭代(enumeration)」的動作,譬如找出其中某些符合條件的東西、對全部東西執行某個動作、等等。

在Objective-C裡,經過時間演進後,有非常多方式可以進行迭代,底下一一描述。

NSArray *array = ...; //假設這是含有一堆字串的陣列

以迴圈手動撰寫,印出陣列裡每一個字串:
for(int i = 0, n = [array count]; i < n; i++){
    NSLog(@"%@", [array objectAtIndex:i]);
}

也可以用NSEnumerator:
NSEnumerator *enumerator = [array objectEnumerator];
NSString *s;
while(s = [enumerator nextObject]){
    NSLog(@"%@", s);
}

不過NSEnumerator已經被Objective-C 2.0新功能Fast Enumeration(for/in語法)取代了:
for(NSString *s in array){
    NSLog(@"%@", s);
}

不僅如此,自從iOS 4之後,還加入了block與新的API(非常多):
[array enumerateObjectsUsingBlock:^void(id obj, NSUInteger idx, BOOL *stop){
    NSLog(@"%@", obj);
}];

照理說,執行效能應該是後面的比前面快,不過我有時候測試一些特殊情況時,並不一定如此。不管如何,block是新機制,Apple也加入不少以block為基礎的API,應該是第一首選才是。

另外,NSDictionary與NSSet也會有差不多的東西,不贅述。

雖然是殺雞用牛刀,底下試試以GCD與Block來迭代陣列。

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply([array count], q, ^(size_t i){
    NSLog(@"%@", array[i]);
});

不過使用的是concurrent queue,NSLog不一定會是從陣列索引值0依序輸出。可自行建立serial queue,便能得到想要的結果。


參考資料:

No comments:

Post a Comment