【iOS】熟悉Objective-C

news2024/10/5 15:32:37

熟悉Objective-C

Objective—C通过一套全新的语法,在C语言基础上添加了面向对象的特性
频繁使用方括号和极长的方法名,使得代码十分易读。

了解Objective-C的起源

Obejective-C与C++,java等面向对象的语言类似,在语法上使用“消息结构”而不是“函数调用”
Objective-C由Smalltalk演化而来,Smalltalk是消息型语言的鼻祖。

	//消息结构【Objective-C】
    NSObject* obj = [NSObject new];
    [obj performWith:paramter1 and:parameter2];
    
    
    //函数调用 【C语言】
    NSObject* obj = new NSObject;
    obj->perfoem(parameter1, parameter2);

区别在于:==使用消息结构的语言,运行时执行的代码块由运行环境来决定,函数调用的语言,由编译器决定。==如果范例中调用的函数是多态的,运行时就要按照“虚方法表”(是编程语言为实现“动态派发”或“运行时方法绑定”采用的一种机制)来查出到底应该执行哪个函数实现。而采用消息结构的语言,不论是否多态,总是在运行的时候才会去查找要执行的方法。
Objective-C的重要工作都由“运行期组件”而非编译器来完成。使用Objective-C的面向对象特性所需的全部数据结构及函数都在运行期间组件里面。
Objective-C是C的“超集”,C语言的所有功能在编写Objective-C时仍然适用。要明白C语言中的“内存模型”,有助于理解Objective-C中的“引用计数”
OC语言中的指针是用来指示对象的,所有OC的对象都必须用指针声明。因为对象所占内存总是分配在“堆空间”而绝不会分配在“栈空间“

分配在堆中的内存必须直接管理,而分配在栈上用于报讯变量的内存则会在其栈帧弹出时自动清理。

Objective-C将堆内存管理抽象出来了,不需要malloc或free来分配或释放对象所占内存。被称为“引用计数”
在OC代码中,遇到的不含*的变量有可能使用“栈空间”,但是这些变量保存的不是OC对象。

在类的头文件中尽量少引入其他头文件

OC使用“头文件”和“实现文件”来区隔代码

  • 使用Objective-C来编写“类”的标准方式为:以类名做文件名,分别创建两个文件,头文件后缀.h,实现文件后缀.m
  • 使用Objective-C来编写任何类几乎都要引入“Foundation.h”。如果不在该类本身引入这个文件,那么就要引入与其超类所属框架对应的“基本头文件”。如:UIViewController的子类的头文件需要引入UIKit.h
  • 在一个类A中需要有另一个类B的对象时,常规操作是给类A的.h文件包含类B的.h文件,“向前声明”该类指在类A的.h文件中并不包含类B的头文件,而是声明 @class B。这种方法适用于不需要知道类B的所有细节,只需要知道有一个类名叫B时。而类A的实现文件中,需要引入类B的头文件。将头文件的引入时机尽量延后,只在确定有需要时才引入,这样可以减少类的使用者所需要引入的头文件数量。向前声明解决了两个类相互引用的问题

如果在类A中有一个类B的属性,而在类B的实现中又用到了类A,如果在各自的头文件中引入对方的头文件,则会导致循环引用。解析一个头文件A时,编译器发现引入了另外一个头文件B,而头文件B又反过来引用头文件A,我们使用#import指令虽然不回导致死循环,但意味着这两个类里有一个无法正确编译。

  • 但是有时候又必须引入其他头文件,如果类继承自超类,则必须引入定义那个超类的头文件,同理,如果要写的某个类遵从某个协议,那么该协议必须有完整定义,且不能向前说明。向前说明只能告诉编译器有某个协议,而此时编译器需要知道该协议中定义的方法。
  • 有时候无法使用向前说明,比如要声明某个类遵守某一项协议,这种情况下,尽量把“该类遵循某协议”的这条声明移至“class-continuation分类”中。如果还不行,就把协议单独放在一个头文件里,然后引入。

多用字面语法,少用与之等价的方法。

  • Objective-C已语法繁杂著称,事实上的确是这样,有一个非常简单的方法可以直接创建NSString对象。这就是“字符串字面量”。如果不使用这个方法,那么就要使用alloc和init方法来创建并初始化对象了。字面量语法也可以来声明NSNumber,NSArray,NSDictionary对象。使用字面量语法,可以缩减源代码长度,使其更为易读
NSString* str = @“Objective-C”;

字面量数值

有时候需要把整数,浮点数,布尔值存入Objective-C对象中,这种情况下可以用NSNumber类。


    NSNumber* num1 = [NSNumber numberWithInt:1];
    
    
    NSNumber* num2 = @1;
    NSNumber* num3 = @2.5f;
    NSNumber* num4 = @2002.6;
    NSNumber* num5 = @YES;
    NSNumber* num6 = @'A';
  • 可以明显看到字面量语法更为简洁明了,声明中只包含数值,而没有多余的语法部分。

字面量数组


    NSArray* array1 = [NSArray arrayWithObjects:@"111", @"222", @"333", nil];
    
    NSArray* array2 = @[@"111", @"222", @"333"];

可以明显看到使用字面量来创建并初始化数组极其简单且易操作。

常规操作数组

  • 数组的常规操作是使用objectAtIndex:方法。

    NSString* str1 = [array1 objectAtIndex:1];
    NSString* str2 = array1[1];

可以明显看到这种操作更为简洁,更易理解。而且和其他语法中使用下标来访问数组的方法类似。

  • ==使用字面量方法来创建数组时,若数组元素对象中含有nil,则会抛出异常。==字面量语法相当于一种“语法糖”(指计算机语言中与另一套语法等效但是开发者用起来更加方便的语法,令程序更加易读,减少代码出错几率)。效果相当于先创建了一个数组,在将方括号内的所有对象都加入这个数组中。
	id str = nil;
    NSArray* array2 = @[@"111", str, @"333"];
    
    NSLog(@"%@", array2);

如果我们这样来初始化数组,会出现一个报错
但是如果我们使用常见方法来创建这个数组,数组内就只包含一个元素,并不会抛出异常。这是因为我们使用字面量方法来创建数组时,实际上还是使用的arrayWithObjects:方法。这个方法会依次处理各个参数,直到遇到nil。这说明字面量方法更为安全有效,抛出异常另程序终止,总比数组里缺少元素要好。
在这里插入图片描述

字面量字典

字典是一种映射结构。传统的创建方法顺序为“对象”,“键”,“对象”,“键”,这种方法不易读懂,如果改用字面量,就非常容易理解了。

	NSDictionary* dic = [NSDictionary dictionaryWithObjectsAndKeys:@"nuonuo", @"yes", @"guoguo", @"no", nil];
    
    
    NSDictionary* dic2 = @{@"nuonuo" : @"yes", @"guoguo" : @"no"};
    
  • 字面量的方法创建字典更为简洁,而且键出现在对象之前,理解起来更为顺畅
  • 与数组一样,字面量创建字典如果中途遇到nil也会抛出异常
  • 字典也可以像数组一样使用字面量方法来访问,增加代码可读性。
	NSDictionary* dic = [NSDictionary dictionaryWithObjectsAndKeys:@"nuonuo", @"yes", @"guoguo", @"no", nil];
    
    
    NSDictionary* dic2 = @{@"nuonuo" : @"yes", @"guoguo" : @"no"};
    
    NSString* str1 = [dic objectForKey:@"no"];
    NSString* str2 = dic[@"no"];
    NSLog(@"%@ %@", str1, str2);

可变数组与字典

通过取下标操作,可以访问数组中某个下标或字典中某个键所对应的元素,如果数组与字典对象是可变的,那么也能通过下标修改其中元素值。

NSMutableArray* arr = [NSMutableArray arrayWithObjects:@"111", @"222", @"333", nil];
    
    NSMutableDictionary* dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"nuonuo", @"yes", @"guoguo", @"no", nil];
    
    [arr replaceObjectAtIndex:1 withObject:@"444"];
    [dic setObject:@"shenqi" forKey:@"yes"];
    
    
    arr[1] = @"444";
    dic[@"yes"] = @"shenqi";

局限性

字面量语法的使用,除了字符串外,创建出来的对象必须属于Foundation框架。如果自定义了这些类的子类,则无法使用字面量方法来创建
使用字面量创建出来的字符串,数组,字典等对象都是不可变的,若想要可变版本的对象,必须复制一份。

    NSMutableDictionary* dic2 = [@[@1, @2, @3] mutableCopy];

多用类型常量,少使用#define预处理指令

如果在一个头文件中进行#define WIDTH 500的操作,那么预处理过程会将所有的WIDTH都换成500。所有引入了这个头文件的代码中的WIDTH都会被替换。
常量名称:若局限于某“编译单元”(实现文件)则在前面加上k,若常亮在类之外可见,则通常以类名为前缀
若不打算公开某个常量,则应该将其定义在使用该常量的文件里。
变量一定要同时用static和const同时修饰,如果试图修改由const修饰符所声明的常量,编译器会报错。static修饰意味着该变量仅在定义此变量的编译单元内可见。
实际上,如果一个变量声明即位const,又为static,那么编译器根本不会创建符号,而是像#define预处理指令一样,把遇到的所有变量替换为常值。
在头文件中使用extern来声明全局变量,并在相关文件中定义其值。这种常量要出现在全局符号表中,所以其名称应该加以区隔,通常用与之相关的类名做前缀。

用枚举表示状态,选项,状态码。

  • 在以一系列常量来表示错误状态码或可组合的选项时,极易使用枚举为其命名。
  • 枚举只是一种常量命名方式,某个对象所经历的各个状态就可以定义为一个简单的枚举集合。由于每种状态都使用一个便于理解的值来表示,所以这样写出来的代码更易读懂。编译器会为枚举分配一个独有的编号,从0开始,每个枚举值递增1。实现枚举所用的数据类型取决于编译器,不过其二进制位的个数必须完全能表示枚举编号。
  • 在定义选项的时候,可以使用枚举类型。若这些选项可以彼此组合,则更应如此。只要枚举定义的对,各选项之间就可以通过按位或操作来组合,按位与操作可以判断出是否已启用某个选项。
  • 可以把逻辑含义相似的一组状态码放入一个枚举集合中,而不要用#define预处理指令或常量来定义。
  • switch语句里,也可以使用枚举来定义。然而,若是用枚举来定义状态机,最好不要有defult分支。这样的话,如果加入新枚举,编译器就会提醒开发者,switch语句并未处理所有枚举。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/86912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【GRU时序预测】基于门控循环单元GRU实现时间序列预测附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

【云原生进阶之容器】第一章Docker核心技术1.3节——命名空间Namespace

1. Linux Namespaces机制简介 Linux Namespace是Linux提供的一种内核级别环境隔离的方法。很早以前的Unix有一个叫chroot的系统调用(通过修改根目录把用户jail到一个特定目录下),chroot提供了一种简单的隔离模式:chroot内部的文件系统无法访问外部的内容。Linux Namespace在…

文件包含漏洞相关协议详解

今天继续给大家介绍渗透测试相关知识,本文主要内容是文件包含漏洞相关协议详解。 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负! 再次强调:严禁对未…

执行 pkg -t win index.js 报错 node.js使用pkg打包成exe可执行文件

文章目录一、问题:当执行命令 pkg -t win index.js 的时候报以下错误:二、解决办法:三、安装pkg流程四、其他的打包方法五、题外话:更换exe的icon图标一、问题:当执行命令 pkg -t win index.js 的时候报以下错误&#…

[附源码]计算机毕业设计点餐系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: Springboot mybatis MavenVue等等组成,B/S模式…

传奇微端架设好后不亮灯是怎么回事微端程序无连接不更新有连接不更新问题解决办法

传奇微端架设好后不亮灯是怎么回事微端程序无连接不更新有连接不更新问题解决办法 这是在架设传奇微端时很多小伙伴都会遇到的问题,今天艾西来教大家怎么解决这个问题 以下图中有打码的望读者理解(平台gz) 网关配置好后,图中几个电…

pikachu靶场-11 SSRF漏洞

SSRF漏洞 概述 SSRF(Server-Side Request Forgery:服务器端请求伪造) 其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制 导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据 数据…

Allegro如何把分离的线段变成封闭连续的图形

Allegro如何把分离的线段变成封闭连续的图形 Allegeo支持把分离的线段变成封闭连续的图形,以下图为例,线段是分离的 具体操作如下 选择shape-compose shape Option选择一个层面,比如画在Board Geometry outline层 Find选择other segs 和Lines 框选图形 鼠标右击选择d…

HTML基础学习笔记合集

HTML学习笔记基础认知基本概念常用标签排版标签标题标签段落标签换行标签(单标签)水平线标签(单标签)文本格式化标签图片标签(单标签)音频标签(双标签)视频标签(双标签&a…

K_A08_013 基于 STM32等单片机驱动大功率MOS管模块按键控制直流电机加减速启停

目录 一、资源说明 二、基本参数 参数 引脚说明 三、驱动说明 大功率MOS模块驱动 对应程序: 四、部分代码说明 接线说明 STC89C52RC大功率MOS模块 STM32F103C8T6大功率MOS模块 五、基础知识学习与相关资料下载 六、视频效果展示与程序资料获取 七、项目主要材料清单 八…

Dockers更新镜像(保留原始数据)

文章目录 一、前言二、使用步骤1.拉取需要更新的镜像版本2.获取当前镜像启动参数3.停止当前镜像4.启动新镜像5.删除旧镜像三、测试验证一、前言 日常工作中,应用程序为了避免漏洞、体验等等肯定是需要定期更新的,使用Docker安装的应用镜像也一样需要定期更新。更新最大的风险…

搭建基于lvs+nginx的负载均衡服务集群

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:蟹黄瓜子文章来源:社区投稿 1.基于四层七层的负载均衡 实现负载均衡的方式有很多,例如…

使用C#写一个Windows服务

创建服务程序 可能你的VS里面没有【Windows服务】这个模板,那么你就需要通过“打开Visual Studio安装程序“,通过VisualStudio Installer来通过“修改”来安装【.NET桌面开发】 通过上面两个地方均可以进入对应的代码文件 public partial class …

4年功能测试月薪9.5K,4个月时间进阶自动化,跳槽涨薪4k后我的路还很长...

前言 最开始我并不是互联网从业者,是经历了一场六个月的培训才入的行,这个经历仿佛就是一个遮羞布,不能让任何人知道,就算有面试的时候被问到你是不是被培训的,我还是不能承认这段历史。我是为了生存,才选…

使用遗传算法计算神经网络的超参数

遗传算法是基于种群的思想,将问题的解通过编码的方式转化为种群中的个体,并让这些个体不断地通过选择、交叉和变异算子模拟生物的进化过程,然后利用“优胜劣汰”法则选择种群中适应性较强的个体构成子种群,然后让子种群重复类似的…

nginx配置websocket支持wss

和前端联调完项目之后,将项目部署到了开发环境上面。结果这时候发现ws连接报错了,怎么回事,明明和前端在本地都联调好了的! 观察报错发现,提示我们需要使用wss连接,而我和前端在对接联调时使用的是ws连接。…

mysql 学习---窗口函数

文章目录Mysql 8.0新特性窗口函数常见窗口函数Mysql 8.0新特性 窗口函数 理解: 窗口函数的作用类似于在查询中对数据进行分组,类似于聚合函数,但不同的是把聚合函数是分组的记录合成一条,也就是一组一条数据,窗口函数…

缓存击穿、缓存穿透、缓存雪崩

初学者总是喜欢自己吓自己,在听到缓存击穿、缓存穿透、缓存雪崩等问题后,就觉得这根本不是自己这个级别所能接触的知识点,甚至不敢下定决心去了解。 然而,缓存击穿、缓存穿透、缓存雪崩等概念只是听着高大上罢了,实则并…

RabbitMq应用

1.RabbitMQ介绍 1.1现存问题 服务调用:两个服务调用时,我们可以通过传统的HTTP方式,让服务A直接去调用服务B的接口,但是这种方式是同步的方式,虽然可以采用SpringBoot提供的Async注解实现异步调用,但是这…

Spring之AOP

谈起AOP就不得不说起代理,Java 源代码经过编译生成字节码,然后再由 JVM 经过类加载,连接,初始化成 Java 类型,可以看到字节码是关键,静态和动态的区别就在于字节码生成的时机 静态代理:由程序员…