effective-Objective-C 第一章阅读笔记

文章目录

OC起源

OC采用的是消息结构,不是函数调用,由Smalltalk演化而来。

消息结构的语言运行时所应执行的代码由运行环境来决定。

使用函数调用的语言则由编译器来决定

函数型语言和消息结构型语言在处理多态时,查找要执行的具体方法的时机和方式不同

  • 基于虚方法表的语言,如C++、Java在编译期,编译器知道类的继承关系和虚函数的签名,每一个类有一个虚方法表,表中存放该类的所有虚函数的实际内存地址,对象内部由一个隐藏指针vptr指向该类的虚表,当调用多态方法时,代码需要先通过对象的cptr指针找到虚表,在表中按照固定偏移找到函数地址,跳转执行。(运行时只查表)
  • 基于消息分发类的语言,如smalltalk、Ruby、早期OC,对象之间通过发送消息来调用方法,编译器通常不绑定方法地址,甚至都不检查方法存不存在,运行时,系统查找对象所属类的方法字典,按照消息名查找对应方法的实现,会沿着继承链向上查找,找不到触发消息无法处理的机制,如调用method_missing或抛出异常,开销比较大

内存管理

OC的部分语法与C语言相同,在OC中使用指针式来指示对象。

objc 复制代码
NSString* str - @"real.";

OC中所有对象都是一个objc_object结构体,我们操作的NSString* 等都是指向这些结构体的指针。这OC中的对象存储在堆/常量区。

objc 复制代码
NSString* str = @"real.";
NSString* antStr = str;

我们看一下这段代码的内存分布:

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

OC采用引用计数管理堆区内存

比起创建结构体,创建对象需要额外的开销,所以有时候采用结构体可以节约内存。

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

在类的头文件中,如果我们需要引入其他文件,使用@class就可以了,实现向前声明,还能避免循环引用

我们在引入协议时,不可以使用向前声明,因为向前声明只能告诉编译器某个协议的存在,而编译器需要知道协议中定义的方法。

多用字面量语法

OC为我们提供了许多语法糖,实现便携书写

objc 复制代码
NSNumber* number = @1
NSNumber* number = @1.6f
NSNumber* number = @YES
NSNumber* number = @'a'
NSNumber* bumber = @(80);
objc 复制代码
NSArray* ary = @[@"ll", @"gg", @"ff"];
ary[1]//字面量取法
objc 复制代码
NSDictionary* data = [@"123":@"213"];
data[@"123"];

在使用字面量语法时,我们需要尽量避免值出现nil,避免抛出异常

多用类型变量,少用#define预处理

objc 复制代码
#define ANIMATION_DURATION 0.8;

如果该宏定义在某个头文件中,那么所有引用这个头文件的代码都会被替换

objc 复制代码
static const int number = 20;

限制该变量只在当前编译单元中可见,避免其他文件被污染
同时可以遵守下面几个规则:

只在当前文件用的常量 → k 前缀

在其他类中可见的话,可以使用类名来做前缀

只要不打算公开这个常量,就在.m文件中定义,并使用static const修饰(保证当前文件可见以及不可修改)

如果不采用static的话,如果在另一个实现文件中定义一个同名变量会报错
其实采用static和const一起来修饰的话,编译器其实还是和#define一样的实现,但是他会有类型信息。

在某些情况下,我们需要给外部一个可见的常量,可以像下面这样定义:

objc 复制代码
extern NSString* *const tom;
extern const int duration;
//.h
NSString *const tom = @"mot";
const int duration = 30;
//.m

注意const修饰的位置,与*结合就是说修饰一个常量指针,与NSString结合就是说修饰一个常量字符串

编译器看到头文件的extern之后就会将其添加到全局符号表中,需要注意避免名称冲突

枚举

objc 复制代码
enum CellType {
    CellTypeSongs
};
typedef enum CellType CellType;
CellType state = CellTypeSongs;

在C++11之后我们可以指定使用何种底层数据类型

objc 复制代码
typedef enum : NSUInteger { //这里保证我们的一个底层数据类型是NSInteger
    <MyEnumValueA>,
    <MyEnumValueB>,
    <MyEnumValueC>,
} <MyEnum>;

我们也可以从某一个值开始手工枚举成员所对应的值。

objc 复制代码
enum CellType {
    CellTypeSongs = 1,
    CellTypeAlbum
};

通过组合枚举实现多选功能

相关推荐
成都渲染101云渲染66667 分钟前
云渲染全面支持3dsMax 2027,高效渲染体验升级
开发语言·前端·javascript
Fuyo_11199 分钟前
C++ 内存管理
c++·笔记
柳鲲鹏37 分钟前
李善兰和牛顿,谁剽窃谁的运动三定律
笔记
向往着的青绿色1 小时前
Java反序列化漏洞(持续更新中)
java·开发语言·计算机网络·安全·web安全·网络安全·网络攻击模型
ZZH_AI项目交付1 小时前
扫脸功能做成 SDK,为什么我没有把结果页和历史记录一起搬进去
ios·app
小短腿的代码世界1 小时前
Qt跨进程通信在交易系统中的应用:让策略引擎与风控模块在毫秒级握手
开发语言·qt
zhangrelay1 小时前
三分钟云课实践速通--大学物理--python 版
linux·开发语言·python·学习·ubuntu·lubuntu
茶底世界之下1 小时前
诡异!String 参数在闭包里变成了 <uninitialized>,我排查了整整两天
ios·xcode·swift
MegaDataFlowers2 小时前
调用Service层操作数据
java·开发语言
asdzx672 小时前
使用 Python 读取 PDF: 提取文本和图片
开发语言·python·pdf