編輯:關於Android編程
NSArray *anArray = /*...*/; for (int i = 0; i < anArray.count; i++) { id object = anArray[i]; //Do something with 'object' }
字典或者set
//Dictionary NSDictionary *aDictionary = /*...*/; NSArray *keys = [aDictionary allKeys]; for (int i = 0; i < keys.count; i++) { id key = keys[i]; id value = aDictionary[key]; //Do something with 'key' and 'value' } //Set NSSet *aSet = /*...*/; NSArray *objects = [aSet allObjects]; for (int i = 0; i < objects.count; i++) { id object = objects[i]; //Do something with 'object' }
字典與set都是無序的。所以無法根據特定的整數下表來直接訪問其中的值。於是,就需要先獲取字典裡的所有鍵或是set裡的所有對象,這兩種情況下,都可以在獲取到的有序數組上遍歷,以便借此訪問原字典及原set中得值。創建這個附加數組會有額外的開銷,而且還會多創建一個數組對象,它會保留collection中得所有元素對象。當然了,釋放數組時這些附加對象也要釋放,可以要調用本來不需要執行的方法。其它各種便利方式都無需創建這種中介數組。
for循環也可以實現反向遍歷,計數器的值從“元素個數減1”,每次迭代時遞減直到0為止。執行反向遍歷時,使用for循環會比其它方式簡單許多。
用Objective-C 1.0中的 NSEnumerator 來遍歷NSEnumerator 是個抽象基類,其中只定義了兩個方法,供其具體子類來實現:
-(NSAraay *)allObjects; - (id)nextObject;
其中關鍵的方法是nextObject,它返回枚舉對象裡的下個對象。每次調用該方法時,其內部的數據結構都會更新,使得下次調用方法時能返回下一個對象。等到枚舉中得全部對象都已返回之後,再調用就將返回nil,這表示達到枚舉末端了。
Foundation框架中內建的collection類都實現了這種遍歷方式。例如,想遍歷數組,可以這樣寫代碼:
NSArray *anArray = /* ... */; NSEnumerator *enumerator = [anArray objectEnumerator]; id object; while ((object = [enumerator nextObject]) != nil) { // Do something with 'object' }
這種寫法的功能與標准的for循環相似,但是代碼卻多了一些。其真正優勢在於:不論遍歷哪種collection,都可以采用這套相似的語法。比方說,遍歷字典及set時也可以按照這種寫法來做:
// Dictionary NSDictionary *aDictionary = /* ... */; NSEnumerator *enumerator = [aDictionary keyEnumerator]; id key; while ((key = [enumerator nextObject]) != nil) { id value = aDictionary[key]; // Do something with 'key' and 'value' } // Set NSSet *aSet = /* ... */; NSEnumerator *enumerator = [aSet objectEnumerator]; id object; while ((object = [enumerator nextObject]) != nil) { // Do something with 'object' }
遍歷字典的方式與數組和set略有不同,因為字典裡既有鍵也有值,所以要根據給定的鍵把對應的值提取出來。使用NSEnumerator 還有個好處,就是有多種“枚舉器”(enumerator)可供使用。比方說,有反向遍歷數組所用的枚舉器,如果拿它來遍歷,就可以按反向來迭代collection中得元素了。例如:
NSArray *anArray = /* ... */; NSEnumerator *enumerator = [anArray reverseObjectEnumerator]; id object; while ((object = [enumerator nextObject]) != nil) { // Do something with 'object' }
Objective-C 2.0引入了快速遍歷這一功能。快速遍歷與使用NSEnumerator來遍歷差不多,然而語法更簡潔,它為for循環開設了in關鍵字。這個關鍵字大幅簡化了遍歷collection所需的語法,比方說要遍歷數組,就可以這麼寫:
NSArray *anArray = /* ... */; for (id object in anArray) { // Do something with 'object' }
這樣寫簡單多了。如果某個類的對象支持快速遍歷,那麼就可以宣稱自己遵從名為NSFastEnumeration的協議,從而令開發者可以采用此語法來迭代該對象。此協議只定義了一個方法:
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id*)stackbuffer count:(NSUInteger)length;
該方法允許類實例同時返回多個對象,這就使得循環遍歷操作更為高效了。
遍歷字典與set也很簡單:
// Dictionary NSDictionary *aDictionary = /* ... */; for (id key in aDictionary) { id value = aDictionary[key]; // Do something with 'key' and 'value' } // Set NSSet *aSet = /* ... */; for (id object in aSet) { // Do something with 'object' }
由於NSEnumerator對象也實現了NSFastEnumeration協議,所以能用來執行反向遍歷數組,可采用下面這種寫法:
NSArray *anArray = /* ... */; for (id object in [anArray reverseObjectEnumerator]) { // Do something with 'object' }
在目前所介紹的遍歷方式中,這種辦法是語法最簡單且效率最高的,然而如果在遍歷字典時需要同時獲取鍵與值,那麼會多出來一步。而且,與傳統for循環不同,這種遍歷方式無法輕松獲取當前遍歷操作所針對的下標。遍歷時通常會用到這個下標,比如很多算法都需要它。
NSArray中定義了下面這個方法,它可以實現最基本的遍歷功能:
- (void)enumerateObjectsUsingBlock:(void(^)(id object, NSUInteger idx, BOOL *stop))block;
在遍歷數組及set時,每次迭代都要執行由block參數所傳入的塊,這個塊有三個參數,分別是當前迭代所針對的對象、所針對的下標,以及指向布爾值的指針。前兩個參數的含義不言而喻。而通過第三個參數所提供的機制,開發者可以終止遍歷操作。
例如,下面這段代碼用此方法來遍歷數組:
NSArray *anArray = /* ... */; [anArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) { // Do something with 'object' if (shouldStop) { *stop = YES; } }];
這種寫法稍微多了幾行代碼,但是依然清晰明了,而且遍歷時既能獲取對象,也能知道其下標。此方法還提供了一種優雅的機制,用於終止遍歷操作,開發者可以通過設定stop變量值來實現,當然,使用其它幾種遍歷方式時,也可以通過break來終止循環,那樣做也很好。
此方式不僅可用來遍歷數組。NSSet裡面也有同樣的塊枚舉方法,NSDictionary也是這樣,只是略有不同:
- (void)enumerateKeysAndObjectsUsingBlock:(void(^)(id key, id object, BOOL *stop))block;
因此,遍歷字典與set也同樣簡單:
// Dictionary NSDictionary *aDictionary = /* ... */; [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) { // Do something with 'key' and 'object' if (shouldStop) { *stop = YES; } }]; // Set NSSet *aSet = /* ... */; [aSet enumerateObjectsUsingBlock:^(id object, BOOL *stop) { // Do something with 'object' if (shouldStop) { *stop = YES; } }];
此方式大大勝過方式的地方在於:遍歷時可以直接從block裡獲取更多信息。在遍歷數組時,可以知道當前所針對的下標。遍歷有序set(NSOrderedSet)時也一樣。而在遍歷字典時,無須額外編碼,即可同時獲取鍵與值,因而省去了根據給定鍵來獲取對應值這一步。用這種方式遍歷字典,可以同時得知鍵與值,這很可能比其他方式快很多,因為在字典內部的數據結構中,鍵與值本來就是存儲在一起的。
另外一個好處是,能夠修改block的方法名,以免進行類型轉換的操作,從效果上講,相當於把本來需要執行的類型轉換操作交給block方法簽名來做。比方說,要用“快速遍歷法”來遍歷字典。若已知字典中得對象必為字符串,則可以這樣編碼:
NSDictionary *aDictionary = /* ... */; for (NSString *key in aDictionary) { NSString *object = (NSString*)aDictionary[key]; // Do something with 'key' and 'object' }
如果改用基於block的方式來遍歷,那麼就可以在block方法簽名中直接轉換:
[aDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { // Do something with 'key' and 'obj' }];
之所以能如此,是因為id類型相當特殊,它可以像本例這樣,為其他類型所覆寫。要是原來的block簽名把鍵與值都定義成NSObject *,那麼就不行了。此技巧出刊不甚顯眼,實則相當有用。指定對象的精確類型之後,編譯器就可以檢測出開發者是否調用了該對象所不具備的方法,並在發現這種問題時報錯。如果能夠確知某collection裡的對象是什麼類型,那就應該使用這種方法指明其類型。
用此方式也可以執行反向遍歷。數組、字典、set都實現了前述方法的另一個版本,使開發者可向其傳入“選項掩碼”(option mask):
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)options usingBlock:(void(^)(id obj, NSUInteger idx, BOOL *stop))block; - (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)options usingBlock: (void(^)(id key, id obj, BOOL *stop))block;
NSEnumerationOptions類型是個enum,其各種取值可用“按位或”(bitwise OR)連接,用以表明遍歷方式。例如,開發者可以請求以並發方式執行各輪迭代,也就是說,如果當前系統資源狀況允許,那麼執行每次迭代所用的block就可以並行執行了。通過NSEnumerationConcurrent選項即可開啟此功能。如果使用此選項,那麼底層會通過GCD來處理並發執行事宜,具體實現時很可能會用到dispatch group。反向遍歷是通過 NSEnumerationReverse選項來實現的。要注意:只有遍歷數組或有序set等有順序的collection時,這麼做才有意義。
總體來看,block枚舉法擁有其他遍歷方式都具備的優勢,而且還能帶來更多好處。與快速遍歷法相比,它要多用一些代碼,可是卻能提供遍歷時所針對的下標,在,在遍歷字典時也能同時提供鍵與值,而且還有選項可以開啟並發迭代功能,所以多寫這點代碼還是值得的。
概覽http是現在主流應用使用的網絡請求方式, 用來交換數據和內容, 有效的使用HTTP可以使你的APP 變的更快和減少流量的使用OkHttp 是一個很棒HTTP客戶端(
activity類處於android.app包中,繼承關系:extends ContextThemeWrapperimplements LayoutInflater.Fa
DrawLayout這個自定義的空間很常見,qq,網易新聞,知乎等等,都有這種效果,那這種效果是怎樣實現的呢?本篇博客將帶你來怎樣實現它。廢話不多說,先來看一下 效果首先
先上效果圖:本篇文章我們來學習一個開源項目Android-ItemTouchHelper-Demo這個項目使用了RecyclerView的ItemTouchHelper類