1 属性修饰符
按特质分类:
- 原子性 atomic、nonatomic
- 内存管理 strong、weak、assign、copy、unsafe_unretained
- 读/写权限 readwrite、readonly
- 方法名 getter=、setter=
- 非空性 nonnull、null_resettable、nullable
atomic
- 原子性属性修饰符
- 默认属性
- 表示对属性的读写是原子操作,确保在多线程环境下读写操作是线程安全的
nonatomic
- 非原子性属性修饰符
- 表示对属性的读写操作不需要考虑线程安全,可以提高属性的访问性能
strong
- 强引用属性修饰符(ARC)
- 会增加引用计数
- 被强引用的对象会在没有任何强引用指向时被释放
retain
- 强引用属性修饰符(MRC)
- 会增加引用计数
- 需要手动在适当的时机释放对象的引用,避免内存泄漏
weak
- 弱引用属性修饰符(ARC)
- 不会增加引用计数
- 编译器在编译时自动生成对象的弱引用,当指向的对象释放后,弱引用会自动置为 nil,避免野指针访问
assign
- 基本数据类型属性修饰符(ARC/MRC)
- 表示直接赋值给属性,不进行引用计数管理
- 在对象被释放后,assign 修饰的指针不会被自动设置为 nil,可能导致野指针访问
copy
- 拷贝属性修饰符(ARC/MRC)
- 表示对属性进行拷贝操作,会创建一个新的对象副本
unsafe_unretain
- 弱引用属性修饰符(ARC)
- 等效于
__unsafe_unretain(MRC) - 类似于 ARC 下的
assign,修饰的指针不会被自动设置为 nil,可能导致野指针访问
readwrite
- 可读写属性修饰符
- 默认属性
- 表示生成属性的 getter 和 setter 方法
readonly
- 只读属性修饰符
- 表示只生成属性的 getter 方法,不生成 setter 方法
getter=
- 自定义属性的 getter 方法名
setter=
- 自定义属性的 setter 方法名
nonnull
- 表示对象引用不应为
nil - 主要用于参数、返回值或属性,用来明确指定对象不能为空
nullable
- 表示对象引用可以为
nil - 主要用于参数、返回值或属性,用来指定对象可以为空
null_resettable
- 表示属性是可重置为
nil的 - 主要用于属性的 setter 方法,当设置为
nil时会将其重置为一个默认值
2 @property @synthesize @dynamic
@property 用于声明一个属性,并指定该属性的特性。
类的属性
- 编译器自动生成 实例变量 + 存取方法声明 + 存取方法实现
分类的属性
-
编译器自动生成 存取方法声明
-
使用关联对象显式实现属性的存取方法
协议的属性
-
编译器自动生成 存取方法声明
-
遵循协议的类显式提供属性的存取方法或使用 @synthesize 自动合成
@synthesize 只能用于在实现文件中,格式 @synthesize 属性名 = 实例变量名;。
- 编译器自动生成 实例变量 + 默认的存取方法实现
- Xcode 4.4前,@property 和 @synthesize 成对出现,@property 生成存取方法声明,@synthesize 生成实例变量和存取方法实现
- Xcode 4.4后,@property 生成实例变量、存取方法声明和实现,@synthesize 功能不变
@dynamic 可用于在接口文件和实现文件中,格式 @dynamic 属性名;。
-
属性的存取方法将由运行时环境提供,而不是由编译器自动生成
-
需要显式提供该属性的存取方法,否则在运行时调用会导致程序崩溃
-
属性的存取方法在运行时会通过消息转发等方式动态处理,比如 Core Data 中的 NSManagedObject 属性
3 const
const 是一个修饰符,用于声明常量。在iOS开发中,const通常用来定义不可变的常量,即一旦赋值后就不能再被修改。
常量指针:指针本身是常量,指向的值不能通过该指针修改。这里 pointer 是一个指向常量整型的指针,即 pointer 本身可以改变指向的对象,但不能通过 pointer 修改指向的整型值。
// 声明一个const常量指针
int value1 = 5;
const int *pointer = &value1;
// 尝试修改指向的值,会导致编译错误
// *pointer = 10;
// 修改指针指向另一个变量
int value2 = 8;
pointer = &value2;
指针常量:指针本身是不可变的常量,指向的值可以通过该指针修改。这里 pointer 是一个常量指针,即 pointer 本身不能改变,但可以通过 pointer 修改指向的整型值。
// 声明一个指针常量
int value3 = 10;
int *const pointer = &value3;
// 可以修改指向的值
*pointer = 15;
NSLog(@"Value: %d", value3);
// 尝试修改指针指向另一个变量,会导致编译错误
// pointer = &value1;
const 修饰 int 常量和指针的写法
const int a;常量整型变量aint const a;常量整型变量a,与第一种写法功能相同const int *p;指向常量整型的指针p,指针所指向的整型值不能通过该指针修改int const *p;指向常量整型的指针p,与第三种写法功能相同int *const p;指向整型的常量指针p,指针本身是不能被修改的,但可以通过该指针修改指向的整型值const int *const p; 指向常量整型的常量指针p,即指针本身和指向的值都不能修改
4 static
static是一个修饰符,具有作用取决于它是应用于全局变量、局部变量还是函数上。
- 静态变量:在函数内部或者全局范围内声明的变量使用 static 关键字来修饰。
- 静态方法:可以用来声明静态方法,即类方法。
- 静态常量:可以使用 static const 关键字来声明全局静态常量。
静态变量具有以下特点:
- 静态局部变量:函数内部声明,只会被初始化一次,保留其值直到程序结束。
- 静态全局变量:全局范围内声明,只能在当前文件中访问。
5 typeof(), __typeof__(), 和 __typeof
三者都是 C 语言特定于编译器的扩展的运算符。
typeof() 和 __typeof__() 是 GNU C/C++ 的扩展,用于获取表达式的类型。
__typeof是 C11 标准中引入的通用泛型选择表达式,用于根据条件选择不同的类型。
6 sizeof
sizeof 是 C/C++ 中用来获取数据类型或变量在内存中所占字节数的关键字。语法形式是 sizeof(expression),其中 expression 可以是任何合法的表达式、类型名或变量名。
在iOS中,变量、指针、数组和结构体的sizeof值取决于数据类型和系统架构(32位或64位):
- 变量
-
char:1字节(32位)/ 1字节(64位)
-
int:4字节(32位)/ 4字节(64位)
-
float:4字节(32位)/ 4字节(64位)
-
double:8字节(32位)/ 8字节(64位)
- 指针
-
char*:4字节(32位)/ 8字节(64位)
-
int*:4字节(32位)/ 8字节(64位)
-
float*:4字节(32位)/ 8字节(64位)
-
double*:4字节(32位)/ 8字节(64位)
- 数组
-
char arr[5]:5字节(32位)/ 5字节(64位)
-
int arr[5]:20字节(32位)/ 20字节(64位)
-
float arr[5]:20字节(32位)/ 20字节(64位)
-
double arr[5]:40字节(32位)/ 40字节(64位)
-
结构体
-
struct Person { char name[20]; // 20字节 int age; // 4字节(按照对齐规则可能会扩展为8字节) }; -
sizeof(struct Person):24字节(32位)/ 24字节(64位)
-
结构体的 sizeof 值受内存对齐规则影响可能会大于成员变量大小之和
-