ObjectiveC-06-循环、逻辑控制、异常处理和程序预处理

2024-03-31 21:12

本文主要是介绍ObjectiveC-06-循环、逻辑控制、异常处理和程序预处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本节详细讲解下程序运行过程中的逻辑控制指令,主要有if等,但在Objective-C中添加了预编译处理指令,这是一个新的内容需要仔细研究下。这节的内容比较简单,但需要多加练习。

循环结构

在ObjC中主要有for、while和do这三种循环结构,do是do while的组合(一般不太常用),一般适合在结尾处开始执行时才用do while语句。

在循环执行代码时可搭配 break 和 continue 语句同时使用;

for

最简单的一种集合循环模式,语法结构for( int =0; condition; exp)。

//for, 除了以下常规的for写法,还有for...in操作int sum = 0;for (int n=1; n<10; n++){sum += n;}NSLog(@"sum is %i", sum);//while        int count=1;while(count<=5){count++;}
//do whileint count=1;do{count++;} while (number<=5)       

for in

这种是一种iterator(迭代器)模式,它与上面的不同之处在于简单,缺点是不能得到循环时的索引值,需要额外定义,在ObjectiveC中很多集合类型都实现了iterator模式。

//初始多个元素的数组
NSArray *myArray = [NSArray arrayWithObjects:@"1",@"2",@"3",@"4",nil];//以字符串遍历
for(NSString *item in myArray ){NSLog(@"this is an element of myArray %@", item);
}//2024-03-31 18:50:18.022629+0800 helloWorld[24475:1026265] 1
//2024-03-31 18:50:18.022917+0800 helloWorld[24475:1026265] 2
//2024-03-31 18:50:18.022948+0800 helloWorld[24475:1026265] 3
//2024-03-31 18:50:18.022968+0800 helloWorld[24475:1026265] 4

选择结构

选择就用字面量if关键字来表示,有如下几种格式:

  • if:一般常用于参数验证
  • if…else:双条件处理,除了A全是B
  • if …else if…else:多条件处理,除了A,B,C外全是D,如果if太多可考虑用switch来代替

if比较简单就不多举例子了,可以按上面三种模式多多练习一下。

if else if else

//**if else if else **
if ( expression1 ){}else if( expression2 ){}else{}

switch

switch可接受int、char、enum。示例如下:

//**switch case**
int flag = 1;
switch(flag){case v1:break;case v2:break;default:break;
}

中断处理

主要包括:return、breadk、continue三种。这三种其实不太好起名字,暂时就叫中断吧,这几种都可用于循环和选择结构中。

return

返回,主要使用场景有两种,一种是可用于方法返回值,另一种是方法的参数验证,比如:

NSString *iftetst(int i){if (i<=5){//参数验证return NULL; }return @"";//方法返回
}

break, continue

用于循环中断,也可以用于switch(多if其实也是循环的一种),示例代码如下:

        NSArray *myArray = [NSArray arrayWithObjects:@"1",@"2",@"3",@"4",nil];//初始多个元素的数组//以字符串遍历,当遇到长度小于4的字符串时直接跳出整个循环for(NSString *item in myArray ){if(item.length<4){break;}NSLog(@"%@", item);}//以字符串遍历,当遇到长度小于4的字符串时直接跳出这次循环,继续下一个循环for(NSString *item in myArray ){if(item.length<4){continue;;}NSLog(@"%@", item);}

异常处理

Cocoa中使用NSException类来表示异常,通常在大型程序开发过程中要封装多个与业务相关的异常,这些异常都必须继承上述的NSException类。APP是否允许异常也可以在Building settings中进行设置。
在这里插入图片描述

关键字

可用的异常处理

  1. @try:定义可抛出异常的代码块
  2. @catch:捕获获常,可以存在多个
  3. @finally:无论是否抛出异常,这段代码都会执行,一般用于资源释放
  4. @throw:在代码中手动抛出异常

捕获异常

@try{Complex *c3 = [Complex class];c3.print;
}@catch(NSException *e){e.reason;
}@finally{e.reason;
}2023-12-20 21:57:17.399690+0800 FractionTest[35583:5256761] +[Complex print]: unrecognized selector sent to class 0x1000087a8
2023-12-20 21:57:17.399889+0800 FractionTest[35583:5256761]  yes

抛出异常

void exceptionTest(){NSException *e = [NSException exceptionWithName:@"" reason:@"" userInfo:[NSNull null]];//方式一,通用@throw  e;//方式二,只对NSException有效[e raise];
}

捕获后抛出

@try{Complex *c3 = [Complex class];c3.print;
}@catch(NSException *e){@throw; //这里不必指定e变量
}

程序预处理

主要是为了方便代码开发、移植和兼容等场景,ObjC中固化的一些特殊代码,这些特殊代码是编译过程的一部分,会在正式程序运行之前优先处理,使用 # 来标记,且在程序文件中必须是行的第一个字母。

typedof 设置别名

如果一个类或变量名字比较长或是特殊时,为当前的数据类型指派另一个名称。 typedof定义的别名只在本类中生效,如果想设计成全局生效,可以使用#define来定义,typeof示例如下:

//原生的 int a; 变量声明可用下面两行来代替
typedof int Counter; //把原生的int关键字起了一个叫Counter的别名Counter a;
//把系统的Number重新起了一个叫NumberObject的API
typedef Number *NumberObject;NumberObject n1, n2, n3;
//枚举别名
typedof enum {january=1, february=2} Month;Month m1, m2;

#define 预定义名称

预定义名称,注意预定义的值不能在程序运行过程中被修改;一般位置在#import之后,命名也建议用全大写字母。

//定义了名称TRUE值为1,之后程序中任何出现TRUE字样的地方都会被替换为1
#define TRUE 1 
gameOver = TRUE; //gameOver==1#define EQUALS ==
if(y EQUALS 0){}

预定义的名称的值可以进行简单的运算。

#define TRUE 1 
#define A TRUE*2gameOver = A; //gameOver==2

带自变量的宏

//如果表达式太长了,可以在行尾加一个 \ 来换行,另外这个year是一个代码中的变量
#define IS_LEAP_YEAR year%4 == 0 && year%100 != 0 || year%400 == 0
if( IS_LEAP_YEAR ) {}//上面的方式可读性比较差,建议改成下面的方式,添加自变量,需要注意的是IS_LEAP_YEAR(y)名称和变量的括号之间没有空格
#define IS_LEAP_YEAR(y) y%4 == 0 && y%100 != 0 || y%400 == 0
if( IS_LEAP_YEAR(year) ) {}

更复杂的宏

#define MakeFract(x,y) ([[Fraction alloc] initWith: x over: y])Fraction *myFra = MakeFract(1, 2);

一个好的实践是把上面这些宏定义在一个单独的.h文件中,然后通过 #import 来引用。

//~~CONST.h
#define TRUE 1
#define FALSE 0//~~Front.m
#import "CONST.h"
gameOver = TRUE;

#ifdef 预编译处理

条件定义

主要包括 #ifndef、#define、 #ifdef、#else 、#endif 这几个语句,这几个语句主要用于同一套代码在不同的设备上运行时的差异化设置。可混在正常代码方法中,不限位置。一个简单的官方例子:

#ifndef Complex_h
#define Complex_h#import <Foundation/Foundation.h>
@interface Complex : NSObject
@end#endif /* Complex_h */

在同一个代码中可以出现多个条件块,比如NSString.h接口

#if !defined(_OBJC_UNICHAR_H_)
#define _OBJC_UNICHAR_H_
#endif#define NS_UNICHAR_IS_EIGHT_BIT 0NS_SWIFT_UNAVAILABLE("Use String or NSString instead.")
@interface NSSimpleCString : NSString {
@packagechar *bytes;int numBytes;#if __LP64__int _unused;
#endif
}

自定义条件

自定义条件编译逻辑,比如应用的代码如下,IPAD为自定义的变量值,在程序中按如下方法使用。

- (id) initWithCoder: (NSCoder *) decoder{#ifdef IPADNSLog(@"AAA");#endifreturn (self);
} 

如果想使上述代码存在意义,可采用三种运行方法:

  • 定义方式1:在某个类中定义
#define IPAD 1
  • 定义方式2:在xcode中定义,位置 Build Settings

在这里插入图片描述

  • 定义方式3:在命令行启动时定义
clang -fobjc -arc -D IPAD main.m -

#if 和 #else 条件判断

可加一些逻辑判断,比如值比较。

#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define NSMaximumStringLength (INT MAX-1)
#endif
#if IPAD>0
#define imageFile @"barHD.png"
#endif

另外一点#ifdef,其实就是#if+#defined的缩写形式,比如:

#if defined(_OBJC_UNICHAR_H_)
#if !defined(_OBJC_UNICHAR_H_)

解除定义

用于消除某些已定义的语句,比如下列代码,如果之前定义了IPAD,之后用undef消除了,则程序不会报错,但所有判断的地方全变为了false。

#undef IPAD 

至此,ObjectiveC语言的基础部分就全部讲述完了,如果能掌握这几章的内容,那么应该可以写一些稍复杂的程序了,比如计算器、数据统计、人机问答(非AI)。后续将讲述一些高级内容,这些高级内容完全是依赖基础的,需要先把基础打牢,尤其是讲到的语法和关键字。

这篇关于ObjectiveC-06-循环、逻辑控制、异常处理和程序预处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/865354

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转