iOS開發實用技巧—Objective-C中的各種遍歷(迭代)方式


  說明:

  1)該文簡短介紹在iOS開發中遍歷字典、數組和集合的幾種常見方式。

  2)該文對應的代碼可以在下面的地址獲得:https://github.com/HanGangAndHanMeimei/Code

?

一、使用for循環

  要遍歷字典、數組或者是集合,for循環是最簡單也用的比較多的方法,示例如下: 

復制代碼
 1 //普通的for循環遍歷
 2 -(void)iteratorWithFor
 3 {
 4     //處理數組//
 5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
 6     NSInteger arrayMCount = [arrayM count];
 7     for (int i = 0; i<arrayMCount; i++) {
 8         NSString *obj = arrayM[i];
 9         NSLog(@"%@",obj);
10     }
11 
12     //處理字典//
13     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
14     NSArray *dictKeysArray = [dictM allKeys];
15     for (int i = 0; i<dictKeysArray.count; i++) {
16         NSString *key = dictKeysArray[i];
17         NSString *obj = [dictM objectForKey:key];
18         NSLog(@"%@:%@",key,obj);
19     }
20 
21     //處理集合//
22     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
23     NSArray *setObjArray = [setM allObjects];
24     for (int i = 0; i<setObjArray.count; i++) {
25         NSString *obj = setObjArray[i];
26         NSLog(@"%@",obj);
27     }
28 
29     //反向遍歷----降序遍歷----以數組為例
30     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
31     NSInteger arrayMCount2 = [arrayM2 count] - 1;
32 
33     for (NSInteger i = arrayMCount2; i>0; i--) {
34         NSString *obj = arrayM2[i];
35         NSLog(@"%@",obj);
36     }
37 }
復制代碼

優點:簡單

缺點:由于字典和集合內部是無序的,導致我們在遍歷字典和集合的時候需要借助一個新的『數組』作為中介來處理,多出了一部分開銷。

?

二、使用NSEnumerator遍歷

NSEnumerator的使用和基本的for循環類似,不過代碼量要大一些。示例如下:

復制代碼
 1 //使用NSEnumerator遍歷
 2 -(void)iteratorWithEnumerator
 3 {
 4     //處理數組//
 5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
 6     NSEnumerator *arrayEnumerator = [arrayM objectEnumerator];
 7     NSString *obj;
 8     while ((obj = [arrayEnumerator nextObject]) != nil) {
 9         NSLog(@"%@",obj);
10     }
11 
12     //處理字典//
13     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
14     NSEnumerator *dictEnumerator = [dictM keyEnumerator];
15     NSString *key;
16     while ((key = [dictEnumerator nextObject]) != nil) {
17         NSString *obj = dictM[key];
18         NSLog(@"%@",obj);
19     }
20 
21 
22     //處理集合//
23     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
24     NSEnumerator *setEnumerator = [setM objectEnumerator];
25     NSString *setObj;
26     while ((setObj = [setEnumerator nextObject]) != nil) {
27         NSLog(@"%@",setObj);
28     }
29 
30 
31     //反向遍歷----降序遍歷----以數組為例
32     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
33     NSEnumerator *arrayEnumerator2 = [arrayM2 reverseObjectEnumerator];
34     NSString *obj2;
35     while ((obj2 = [arrayEnumerator2 nextObject]) != nil) {
36         NSLog(@"%@",obj2);
37     }
38 
39 }
復制代碼

優點:對于不同的數據類型,遍歷的語法相似;內部可以簡單的通過reverseObjectEnumerator設置進行反向遍歷。

缺點:代碼量稍大。

?

三、使用for...In遍歷

在Objective-C 2.0 中增加了for ...In 形式的快速遍歷。此種遍歷方式語法簡潔,速度飛快。示例如下:

復制代碼
 1 //使用for...In進行快速遍歷
 2 -(void)iteratorWithForIn
 3 {
 4     //處理數組//
 5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
 6     for (id obj in arrayM) {
 7         NSLog(@"%@",obj);
 8     }
 9 
10     //處理字典//
11     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
12     for (id obj in dictM) {
13         NSLog(@"%@",dictM[obj]);
14     }
15 
16     //處理集合//
17     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
18     for (id obj in setM) {
19         NSLog(@"%@",obj);
20     }
21 
22     //反向遍歷----降序遍歷----以數組為例
23     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
24     for (id obj in [arrayM2 reverseObjectEnumerator]) {
25         NSLog(@"%@",obj);
26     }
27 }
復制代碼

優點:1)語法簡潔;2)效率最高;

缺點:無法獲得當前遍歷操作所針對的下標。

?

四、基于Block的遍歷方式

基于Block的方式來進行遍歷是最新引入的方法。它提供了遍歷數組|字典等類型數據的最佳實踐。示例如下:

復制代碼
 1 //基于塊(block)的遍歷方式
 2 -(void)iteratorWithBlock
 3 {
 4     //處理數組//
 5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
 6     [arrayM enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
 7         NSLog(@"%zd--%@",idx,obj);
 8     }];
 9 
10     //處理字典//
11     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
12     [dictM enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
13         NSLog(@"%@:%@",key,obj);
14     }];
15 
16     //處理集合//
17     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
18     [setM enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
19         NSLog(@"%@",obj);
20     }];
21 
22     //反向遍歷----降序遍歷----以數組為例
23     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
24     [arrayM2 enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
25         NSLog(@"%zd--%@",idx,obj);
26     }];
27 }
復制代碼

優點:1)遍歷時可以直接從block中獲得需要的所有信息,包括下標、值等。特別相對于字典而言,不需要做多余的編碼即可同時獲得key和value的值。

   2)能夠直接修改block中key或者obj的類型為真實類型,可以省去類型轉換的工作。

   3)可以通過NSEnumerationConcurrent枚舉值開啟并發迭代功能。

說明:基于Block的遍歷方式在實現反向遍歷的時候也非常簡單,使用enumerateObjectsWithOptions方法,傳遞NSEnumerationReverse作為參數即可,在處理遍歷操作的時候推薦基于Block的遍歷方式。

?

五、使GCD中的dispatch_apply函數

  使用GCD中的dispatch_apply函數也能實現字典、數組等的遍歷,該函數比較適合處理耗時較長、迭代次數較多的情況。示例如下:

復制代碼
 1 //使用GCD中的dispatch_apply函數
 2 -(void)iteratorWithApply
 3 {
 4     //處理數組//
 5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
 6 
 7     //獲得全局并發隊列
 8     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
 9 
10     dispatch_apply(arrayM.count, queue, ^(size_t index) {
11         NSLog(@"%@--%@",arrayM[index],[NSThread currentThread]);
12     });
13 }
復制代碼

優點:開啟多條線程并發處理遍歷任務,執行效率高。

缺點:1)對于字典和集合的處理需借助數組;2)無法實現反向遍歷。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248027.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248027.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248027.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

windows系統作為客戶端時,linux中本地yum源掛載時,如何同時掛載DVD1和DVD2?

這里以CentOS6.5為例.他的鏡像有兩個DVD1和DVD2.DVD1中是系統和主要的安裝包,DVD2中是剩下的安裝包 當掛載時如果要同時掛載DVD1和DVD2.需要這樣做: 1)在虛擬機的設置中選擇連接 2)分別在mnt下創建cdrom和cdrom1文件夾 3)到dev下查看有軟連接 cdrom->sr0 cdrom1->sr1 這里…

Ajax — 大事件項目(第二天)

大事件-02 fix一個bug 原因&#xff1a; 開始做注冊的時候&#xff0c;頁面中只有一個 namepassword的input&#xff0c;所以 $(‘input[name“password”]’) 可以準確的找到元素后來做登錄的時候&#xff0c;頁面中多了一個namepassword的input&#xff0c;所以$(‘input[…

OpenCV自帶dnn的Example研究(3)— object_detection

這個博客系列&#xff0c;簡單來說&#xff0c;今天我們就是要研究https://docs.opencv.org/master/examples.html下的6個文件&#xff0c;看看在最新的OpenCV中&#xff0c;它們是如何發揮作用的。在配置使用的過程中&#xff0c;需要注意使用較高版本的VS避免編譯器兼容問題&…

Ajax — 大事件項目(第三天)

大事件-03 用戶信息 表單驗證 html中&#xff0c;直接使用layui提供的內置驗證規則 email <input type"text" name"email" required lay-verify"required|email" placeholder"請輸入郵箱" autocomplete"off" class&q…

iOS中監測來電方案

問題 最近在做一個有錄音功能的App&#xff0c;要求當用戶接到來電時&#xff0c;要停止錄音。該如何實現這個功能呢&#xff1f; 解決方案 我首先想到了AppDelegate里的applicationWillResignActive:方法&#xff0c;在該方法的注釋中就寫到到收到來電或短信時&#xff0c;系統…

iOS運行時-使用Runtime向Category中添加屬性以及運行時介紹

前言 了解OC的都應該知道&#xff0c;在一般情況下&#xff0c;我們是不能向Category中添加屬性的&#xff0c;只能添加方法&#xff0c;但有些情況向&#xff0c;我們確實需要向Category中添加屬性&#xff0c;而且很多系統的API也有一些在Category添加屬性的情況&#xff0c;…

Ajax — cropper (圖片剪裁)基本用法

jQuery-cropper插件完整的API&#xff1a;http://www.jq22.com/jquery-info9322 1. 基本使用步驟 在 <head> 中導入 cropper.css 樣式表&#xff1a; <link rel"stylesheet" href"/assets/lib/cropper/cropper.css" />在 <body> 的結…

「短篇小說」靈囚 540 天

轉載&#xff1a;知乎 - BIMBOX 孫彬 - https://zhuanlan.zhihu.com/p/24655832 「我們總有一天會逾越那條上帝劃好的界限&#xff0c;而最終我們將無法面對真實和虛假&#xff0c;正義與罪惡。」 「不幸的是&#xff0c;從伊甸園那一次&#xff0c;我們就已經越界了。」 第十天…

iOS 夠逼格的注釋總結

首先關于注意這里就不說什么VVDocument了&#xff0c;來點新鮮的&#xff01; 也許你使用過#warning 警告提示 也許你也使用過#pragma marks。 但是你見過或者使用過下面這個嗎&#xff1f; Comments containing:MARK:TODO:FIXME:!!!:???: 沒有&#xff0c;那么你就快速的看…

Git圖形化管理工具

Git圖形化管理工具 注意&#xff1a;必須在創建的倉庫中進行右鍵打開 復制這段內容后打開百度網盤App&#xff0c;操作更方便哦。 鏈接&#xff1a;https://pan.baidu.com/s/1eXIk01LXSmzmXvYfw3MnEA 提取碼&#xff1a;J166 --來自百度網盤超級會員V5的分享 分類 sourceTr…

TCP/IP(一):數據鏈路層

背景 這一系列的文章主要是為一般的、非專業開發崗位(如移動端)的工程師準備&#xff0c;一方面可以對網絡的基本知識有基本的了解&#xff0c;另一方面不至于面試中被問到相關問題時束手無策。知識以 TCP/IP 協議簇為主&#xff0c;也會有應用層和數據鏈路層的簡單介紹。 文…

富文本和封面制作

1. 富文本編輯器的實現步驟 添加如下的 layui 表單行&#xff1a; <div class"layui-form-item"><!-- 左側的 label --><label class"layui-form-label">文章內容</label><!-- 為富文本編輯器外部的容器設置高度 --><div…

Linux系統編程——線程(1)

目錄 線程概要Linux內核線程實現原理線程的共享/不共享資源線程優缺點線程控制原語pthread_selfpthread_createpthread_exitpthread_joinpthread_cancel終止線程方式控制原語對比前情提要&#xff1a; Linux用戶級線程和內核級線程區別 線程概要 Linux內核線程實現原理 類Unix系…

TCP/IP(二):IP協議

IP協議處于OSI參考模型的第三層——網絡層&#xff0c;網絡層的主要作用是實現終端節點間的通信。IP協議是網絡層的一個重要協議&#xff0c;網絡層中還有ARP(獲取MAC地址)和ICMP協議(數據發送異常通知) 數據鏈路層的作用在于實現同一種數據鏈路下的包傳遞&#xff0c;而網絡層…

Ajax — 大事件項目(第四天)

分類管理 添加分類 初步使用彈出層 給 “添加分類” 綁定一個單擊事件單擊事件中&#xff0c;使用 layer.open() 實現一個彈出層 type: 1, 彈層的類型是頁面層title, “添加文字分類”content: ‘字符串&#xff0c;DOM’,area: [‘500px’, ‘250px’] // ---------------…

redis學習(四)

一、Redis 鍵(key) 1、Redis 鍵命令用于管理 redis 的鍵。 2、Redis 鍵命令的基本語法如下&#xff1a;redis 127.0.0.1:6379> COMMAND KEY_NAME 3、常用key命令 keys * 獲取所有的keyselect 0 選擇第一個庫move myString 1 將當前的數據庫key移動到某個…

TCP/IP(三):IP協議相關技術

在前兩篇文章中&#xff0c;我分別介紹了數據鏈路層和網絡層的IP協議。雖然這個系列教程的重點是搞定 TCP/IP&#xff0c;不過不用著急&#xff0c;本文簡要介紹完與 IP 協議相關的技術&#xff0c;下一篇文章就會正式、詳細的介紹 傳輸層與 TCP 協議。這篇文章會介紹 DNS、ARP…

Node — 第一天

Node-01 會 JavaScript&#xff0c;就能學會 Node.js&#xff01;&#xff01;&#xff01; **Node.js 的官網地址&#xff1a; ** Node.js 的學習路徑&#xff1a; JavaScript 基礎語法 Node.js 內置 API 模塊&#xff08;fs、path、http等&#xff09; 第三方 API 模塊&…

TCP/IP(四):TCP 與 UDP 協議簡介

從本章開始&#xff0c;我們開始介紹最重要的傳輸層。傳輸層位于 OSI 七層模型的第四層&#xff08;由下往上&#xff09;。顧名思義&#xff0c;傳輸層的主要作用是實現應用程序之間的通信。網絡層主要是保證不同數據鏈路下數據的可達性&#xff0c;至于如何傳輸數據則是由傳輸…

Node — 第二天

http模塊 搭建服務器的步驟 ① 導入 http 模塊 ② 創建 web 服務器實例 ③ 為服務器實例綁定 request 事件&#xff0c;監聽客戶端的請求 ④ 啟動服務器 // ① 導入 http 模塊 const http require(http);// ② 創建 web 服務器實例 const server http.createServer();/…