2013年8月24日 星期六

Array 的列舉

在早期 C 語言 Array 的列舉有兩種方法,分別為 for 與 for-in 兩種,
到了 Objective-C 這兩種方法也是繼續存在,不過除此之外多了另一個新的方法,
是採用 block 的 enumerate 的方式,它的好處是它會使用另一個 Thread 去處理,
不會影響原本的 Thread 導致畫面凍結的問題,至於這三個要怎麼使用就由我來做教學。

首先假設有一個 Array 名稱為 sampleArray,它的 Code 如下:
	NSArray *sampleArray = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"0", nil];

首先是最簡單的 for 列舉的方式,另外故意在列舉到 8 的時候停止,
至於為什麼,我就慢點再解答了。
	NSLog(@"For 的結果:");
	for (int i = 0; i <= sampleArray.count - 1; i++) {
		NSString *symbol = (NSString *)sampleArray[i];
		NSLog(@"%@", symbol);
	
		if ([symbol isEqualToString:@"8"]) {
			break;
		}
	}
結果如下:








接下來就是 for-in 的列舉,同樣列舉到 8 的時候停止。
	NSLog(@"For in 的結果:");
	for (NSString *symbol in sampleArray) {
		NSLog(@"%@", symbol);
	
		if ([symbol isEqualToString:@"8"]) {
			break;
		}
	}
結果如下:








最後是上面所說的 enumerate 的方式,同樣列舉到 8 的時候停止,
這時停止列舉的方式就與之前的完全不一樣了,這是因為在 block 中無法使用 break; ,所以折衷方案就變成這樣子了。
另外預設的 block 回傳內容如右:^(id obj, NSUInteger idx, BOOL *stop),
其中的 id obj 可以改為對應的 Array 內容,如果你的 Array 內容不固定的話,那還是使用預設的內容。
	NSLog(@"Enumerate 的結果:");
	[sampleArray enumerateObjectsUsingBlock:^(NSString *symbol, NSUInteger idx, BOOL *stop) {
		NSLog(@"%@", symbol);
	
		if ([symbol isEqualToString:@"8"]) {
			*stop = YES;
		}
	}];
結果如下:








另外 enumerate 的列舉有另一個方法,就是反向列舉,使用方法如下:
	NSLog(@"Enumerate Reverse 的結果:");
	[sampleArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSString *symbol, NSUInteger idx, BOOL *stop) {
		NSLog(@"%@", symbol);
	
		if ([symbol isEqualToString:@"8"]) {
			*stop = YES;
		}
	}];
這時候的結果如下:




基本上 enumerate 的列舉的效能比起另外兩個好上很多,
主要是它是使用另外一個 Theard 來處理的,不過成也 Theard,敗也 Theard,
要是你在列舉的過程中需要使用非同步的處理的話,就 enumerate 的列舉會讓你進入一陣混亂,
因為非同步的處理也是使用另一個 Theard 來處理的,因此會導致在另一個 Theard 中又進入了另一個 Theard,
這會讓這個程式超出你的掌控,所以這時候必須改回原始的 for 或是 for-in 來列舉。


最後,這次的教學到此為止,大家下次再見了。

沒有留言: