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

相关文章

Python程序的文件头部声明小结

《Python程序的文件头部声明小结》在Python文件的顶部声明编码通常是必须的,尤其是在处理非ASCII字符时,下面就来介绍一下两种头部文件声明,具有一定的参考价值,感兴趣的可以了解一下... 目录一、# coding=utf-8二、#!/usr/bin/env python三、运行Python程序四、

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

Python处理大量Excel文件的十个技巧分享

《Python处理大量Excel文件的十个技巧分享》每天被大量Excel文件折磨的你看过来!这是一份Python程序员整理的实用技巧,不说废话,直接上干货,文章通过代码示例讲解的非常详细,需要的朋友可... 目录一、批量读取多个Excel文件二、选择性读取工作表和列三、自动调整格式和样式四、智能数据清洗五、

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结

Python使用python-docx实现自动化处理Word文档

《Python使用python-docx实现自动化处理Word文档》这篇文章主要为大家展示了Python如何通过代码实现段落样式复制,HTML表格转Word表格以及动态生成可定制化模板的功能,感兴趣的... 目录一、引言二、核心功能模块解析1. 段落样式与图片复制2. html表格转Word表格3. 模板生

redis在spring boot中异常退出的问题解决方案

《redis在springboot中异常退出的问题解决方案》:本文主要介绍redis在springboot中异常退出的问题解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴... 目录问题:解决 问题根源️ 解决方案1. 异步处理 + 提前ACK(关键步骤)2. 调整Redis消费者组

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

springboot项目redis缓存异常实战案例详解(提供解决方案)

《springboot项目redis缓存异常实战案例详解(提供解决方案)》redis基本上是高并发场景上会用到的一个高性能的key-value数据库,属于nosql类型,一般用作于缓存,一般是结合数据... 目录缓存异常实践案例缓存穿透问题缓存击穿问题(其中也解决了穿透问题)完整代码缓存异常实践案例Red

Python Pandas高效处理Excel数据完整指南

《PythonPandas高效处理Excel数据完整指南》在数据驱动的时代,Excel仍是大量企业存储核心数据的工具,Python的Pandas库凭借其向量化计算、内存优化和丰富的数据处理接口,成为... 目录一、环境搭建与数据读取1.1 基础环境配置1.2 数据高效载入技巧二、数据清洗核心战术2.1 缺失

SpringBoot项目中Redis存储Session对象序列化处理

《SpringBoot项目中Redis存储Session对象序列化处理》在SpringBoot项目中使用Redis存储Session时,对象的序列化和反序列化是关键步骤,下面我们就来讲讲如何在Spri... 目录一、为什么需要序列化处理二、Spring Boot 集成 Redis 存储 Session2.1