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
};

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

相关推荐
jghhh012 小时前
基于C#的CAN总线BMS上位机开发方案
开发语言·c#
serve the people2 小时前
python环境搭建 (七) pytest、pytest-asyncio、pytest-cov 试生态的核心组合
开发语言·python·pytest
java1234_小锋2 小时前
分享一套不错的基于Python的Django宠物信息管理系统
开发语言·python·宠物
一切尽在,你来2 小时前
C++ 零基础教程 - 第4讲-实现简单计算器
开发语言·c++
女王大人万岁2 小时前
Go语言JSON标准库(encoding/json):功能解析与实战指南
服务器·开发语言·后端·golang·json
暴躁小师兄数据学院2 小时前
【WEB3.0零基础转行笔记】基础知识篇-第二讲:以太坊基础
笔记·web3·区块链
恋猫de小郭2 小时前
小米 HyperOS 4 大变样?核心应用以 Rust / Flutter 重写,不兼容老系统
android·前端·人工智能·flutter·ios
wjs20242 小时前
Scala 基础语法
开发语言
.ZGR.2 小时前
从游戏到实战的线程进阶之旅:智能无人机防空平台
java·开发语言·无人机