![iOS开发:从零基础到精通](https://wfqqreader-1252317822.image.myqcloud.com/cover/796/26793796/b_26793796.jpg)
2.3 循环结构
在Objective-C中,经常会遇到重复执行同一段代码的情况,这时候就会使用到循环功能。和其他编程语言一样,Objective-C也提供循环结构的语法,包括for循环、while循环和do-while循环。循环的本质就是重复一定的次数来执行某段语句,一般应用循环结构基本就是执行累加或者遍历对象等类似操作。
2.3.1 for循环
1.for循环简介
for循环是最常使用的循环方式。for循环是开界的,它的一般形式为:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T42_5217.jpg?sign=1738855429-oMXsYY3TuSiRSBm0RIq68gKyATzhqPET-0-dc3d216fc7d3baf9aae1b0baca7ebde4)
其中:
- 初始化总是一个赋值语句,它用来给循环控制变量赋初值。
- 条件表达式是一个关系表达式,它决定什么时候退出循环。
- 增量定义循环控制变量每循环一次后按什么方式变化。
这三个部分之间用分号分开。
例如下方的代码,先给i赋初值1,判断i是否小于等于10。若是,则执行语句,之后i的值增加1。再重新判断,直到条件为假,即i>10时,结束循环。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T42_5219.jpg?sign=1738855429-vwMoQicS5ax21dbIiRBJAIkt2oFnTlqF-0-342089ae4491d9bb44c1c2d6b8b73219)
2.for循环的实现形式
除了上面介绍的简单for循环之外,for循环中还可以嵌套for循环,从而实现一些复杂的循环操作。例如,当一个数组中嵌套了另外若干个数组的情况下,就可以使用嵌套for循环的方式来取出数组中存储的每个对象。
- 简单的for循环。下方的代码实现了打印0~9这10个数字。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T42_5221.jpg?sign=1738855429-kbRzUXu8QgCWxzN9o5BsKSFF9HuVGxrh-0-4a323fb8fbd29f5618ea3c171be41bd3)
运行结果如图2-9所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P43_5341.jpg?sign=1738855429-XXw62DezQiDS9qcs6ozbEGKCLxOxuiLW-0-11884e75caf26575ddb3363fe2dd387d)
图2-9 运行结果
- 嵌套的for循环。示例代码中实现了求解从1~5这5个数字先计算每个数字的阶乘,然后再累加求和。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T43_5345.jpg?sign=1738855429-uDAcpqEYvkWxtiwto8nCo7cLdlrLnsXr-0-81250933ba8100409adcb710fd6ea783)
运行结果如图2-10所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P43_5347.jpg?sign=1738855429-BLL7SivWRkYGk73TvIZZKs29MMyZYWd7-0-80dac2f142e07d3f1e735203558f60b6)
图2-10 运行结果
3.for循环的循环条件
在编写for循环时可能会遇到在开始循环之前需要初始化多个变量,或者每次循环要计算多个表达式的情况。其实在for循环的任何位置都可以包含多个表达式,只要用逗号分隔这些表达式即可。例如,使用以下形式开始的for循环,在循环开始之前,将i的值设为0,j的值设为100,每次执行完循环体后,i的值加1,j的值减1。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T44_5452.jpg?sign=1738855429-pjcU88gU941mAP5U0hOVAQDV3esUXzPT-0-4784c6695409019b2b445495294a6bc7)
既然for循环中字段的表达式可以不止一个,那么省略for循环中的一个或多个字段也是可以实现的。省略for语句中某个字段的最常见情形发生在无须计算初始表达式的值时。在这种情况下,for语句的第一个字段可以简单地保留空白,只要仍然保留分号即可。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T44_5454.jpg?sign=1738855429-COLDwjUd01rlLYJetJLcVs2ZPfWALFIz-0-6bd32935c6b8776d39de291681e78138)
如果省略了for语句的第二个字段,那么这条for语句实际上就是无限循环的,因为循环条件永远为真,如果需要退出循环就需要执行return、break或goto语句。开发者也可以使用在for循环中定义循环变量的做法,比如for(int i=0;i<10;i++)的写法,这个i就是该for循环的局部变量了,离开for循环就无法访问。
2.3.2 for-in循环
1.for-in循环使用说明
在Objective-C编程中,for-in循环可以认为是一种增强型的for循环,这个是Objective-C中的一个重要语法。当遇到遍历数组的情况时经常会使用到for-in循环。例如下方的代码中,创建了一个数组,并且在数组中存储了一些字符串对象。开发者可以使用for-in循环来遍历数组中的每一个对象,并打印出其存储的文字内容。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T44_5458.jpg?sign=1738855429-T5f3v5QdBqJsFT9QZ86FxQjOHo0ujSQv-0-321e9d82714e6ba08978671d1535691c)
运行结果如图2-11所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P45_5588.jpg?sign=1738855429-thIdSTVIuIXCHQKWkgucEaApS2SrO5oJ-0-b2bfa7d50425e4de03e6779f85bdb5cc)
图2-11 运行结果
对于for-in循环来说,完全可以使用简单的for循环来替代,例如,使用for循环来修改上面的示例代码,同样可以实现相同的功能,但是通过对比可以发现,使用for-in循环要简便很多。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T45_82803.jpg?sign=1738855429-xQ2CdKeqo7RXtMCdEJCwppkyFO1gByGc-0-b1bcddb012570089f094989efc9aef0b)
2.for-in循环使用注意事项
快速枚举的过程中不允许改变容器中的对象,即不允许删除或者增加枚举容器中的对象。因为对于一个既定的枚举器来说,其内部的对象都已经对其进行了枚举排序,如果你私自添加或者删除对象,那么其既定的枚举序列就发生了改变,而这种改变是系统不能识别的,所以Objective-C中不允许这么做。例如,在下面的示例中,在遍历的过程中对数组容器的内容进行了修改,运行时程序就会崩溃,提示的错误原因是:“Collection was mutated while being enumerated”。这个错误是说集合在枚举的过程中发生了突变,执行这样的操作会得到未定义的结果。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T45_5595.jpg?sign=1738855429-cOkKZLEFPwzoxblG62ri5F4GEgUhzpqX-0-b0c2ec068599ae61544e5ff925544081)
运行报错如图2-12所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P46_5702.jpg?sign=1738855429-F8VbZ12DyunkpFWnwnPFNKITxlnhYhcm-0-e8e68db2dea91754e34a327a954d88ab)
图2-12 运行报错原因
但有时也必须在快速枚举的过程中删除一些枚举容器中的对象,这时就需要在删除完一个对象时,对循环执行进行break操作。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T46_5706.jpg?sign=1738855429-iihEQan47XG3UEDGBwd9nmk2cSRRtkmh-0-118194935bd798295f832aa93a4071e2)
2.3.3 while循环
在Objective-C语言中,除了最常使用的for循环以及for-in循环之外,还存在其他几种循环方式,例如:while循环、do-while循环等。
1.while语句
while语句的一般形式为:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T46_5709.jpg?sign=1738855429-Yh7pi76tfsu6rDcurMkaNVHb9v3RlPsP-0-51c31fe71e56d6c1735e1cb829e44dc9)
其中:
表达式 循环条件;
大括号{} 内的语句为循环体。
while语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体语句。执行完循环体后再次计算表达式的值,如果值为真,再次执行循环体语句,直到表达式的最终求值结果为假时,循环终止。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T47_5848.jpg?sign=1738855429-u5idmTQ6TmdamS0gKjwIyeuHkeeDwfYJ-0-df738e7d861894700cc0eba320c0ebd7)
运行结果如图2-13所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P47_5850.jpg?sign=1738855429-0qm1L31fcDShhhtMa8y9pxzbltbZZ9w5-0-504b6b2a80dd084761290a237fc28515)
图2-13 运行结果
2.do-while语句
do-while语句的一般形式为:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T47_5854.jpg?sign=1738855429-krKyrbWCYIijYee2XP1ztWUMEbNyz4Ra-0-99c128b972f2d88d2aed8abcf4c9a39a)
do-while语句只是while语句的简单转置,它把循环条件放在循环的结尾部分,这样就会先执行循环体中的语句,再判断条件表达式的真假。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T47_5856.jpg?sign=1738855429-VwfxfqzQLlvhf5xFzfjDi3ENruiHoyr6-0-5f09edceadae338a99bd61ff754ca8b1)
运行结果如图2-14所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P48_5939.jpg?sign=1738855429-TSFiVbJthn6wEEy76McF9EkiUHcUfTTD-0-1fa1385d7fba0b846842bcbafe6db78d)
图2-14 运行结果
上例中循环条件是i<2,但是i的初始值是3,不满足循环条件,但是循环体还是被执行了一次,所以说明do-while语句可以确保循环体至少执行一次。
2.3.4 break与continue
1.break语句
在执行循环的过程中,有时候程序员会希望在发生特定条件时退出循环。例如:检测到错误条件或者在遍历一系列数据时查找到了需要的记录时就及时退出循环。break语句就可以实现这个目的。只要执行了break语句,程序将立即退出正在执行的循环,循环内break语句之后的代码将被跳过,不会被执行,并且该循环的执行也将终止,程序会执行该循环之外的其他内容。
如下所示的for循环中,当i等于5时,可以使用break退出循环。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T48_5945.jpg?sign=1738855429-o1sASrJOGWG9Q2jDvyDxRMEMCbbxufOF-0-27a4f35ba143a31796786a887ac374f5)
运行结果如图2-15所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P48_5947.jpg?sign=1738855429-9eUM0hVMf8ZsWxJlY5iGHDM8oeEcS1hS-0-5bc821030ef3b14df2be055364d0f9b7)
图2-15 运行结果
2.continue语句
continue语句和break语句类似,但它并不会使循环结束。执行continue语句时,循环会跳过continue语句之后直到循环结束处的所有语句。但是并不会阻止满足循环条件的循环体的下一次执行。continue语句通常用来根据某个条件绕过循环中的某一组语句。
例如,在下方的代码中,当i等于2时,下面的打印i值的语句会被跳过,继续执行下一次循环。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T49_6049.jpg?sign=1738855429-UVbOt76Ep7iXg0x1R1T5U3kXNxevKdHR-0-c984d3acfbc35bff123adebbd47a9423)
运行结果如图2-16所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P49_82804.jpg?sign=1738855429-sbpnyF6OcOAMXbX6fUMUL0VCt5tqu8TW-0-bb3d2e144ed58392ddcc000c844979d4)
图2-16 运行结果
在实际的开发过程中,如果不是必要的情况下,不建议使用break语句或者continue语句,因为这样会增加程序的阅读难度。