1. 类的定义和实现LGPerson
-
成员变量
:类的定义或者类的实现中,在{ }
中所声明的变量都为成员变量
。成员变量用于类内部
(不会生成setter、getter方法
),不需与外界接触
的变量。 -
实例变量
:是一种特殊的成员变量
,实例变量本质上就是成员变量,只是实例是针对类而言,实例是指类的声明
,如果成员变量的类型是类类型
,那么这样的成员变量就是实例变量
-
属性
:为方便类对象通过点语法访问了属性
,编译后会生成带下划线的成员变量
, 属性创建过程中自动产生了setter 和getter方法和带下划线的成员变量
。可以设置只读
或者可写
等,设置方法也可自定义
。属性是用于提供外部访问
的变量。
2. clang 编译查看.cpp文件
clang编译命令
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.2.sdk main.m
3. strong & copy & weak 底层分析
- 用copy和strong修饰的属性,clang编译成.cpp后setter方法不同
copy修饰的属性使用了objc_setProperty,而strong修饰的没有?
- 在LLVM源码中搜索
”objc_setProperty
,找到getOptimizedSetPropertyFn
方法
针对不同的修饰符,返回的name是不同的:
-
如果是
atomic & copy
修饰,name为objc_setProperty_atomic_copy
-
如果是
atomic 且没有copy
修饰,name为objc_setProperty_atomic
-
如果是
nonatomic & copy
修饰,name为objc_setProperty_nonatomic_copy
-
其他剩余的组合,即
nonatomic、nonatomic & strong、nonatomic & weak
等,name为objc_setProperty_nonatomic
llvm编译属性流程: 属性的setter方法setPropety进入llvm后,llvm遍历ivar进行优化处理,对修饰符判断返回一个sel绑定一个value
上述的几个name分别对应objc-781源码中的如下方法
然后通过汇编调试发现,最终copy和strong修饰的属性都会走到objc_storeStrong
- copy修饰的属性汇编调试结果
- strong修饰的属性汇编调试结果
- 源码中搜索
objc_storeStrong
,有如下源码,主要也是retain新值,release旧值
void
objc_storeStrong(id *location, id obj)
{
id prev = *location;
if (obj == prev) {
return;
}
objc_retain(obj);//retain新值
*location = obj;
objc_release(prev);//release旧值
}
结论
copy
和strong
修饰的属性在底层编译的不一致,主要还是llvm中对其进行了不同的处理的结果。copy
的赋值是通过objc_setProperty
,而strong的赋值时通过self + 内存平移
(即将指针通过平移移至name所在的位置,然后赋值),然后还原成strong
类型strong & copy
在底层调用objc_storeStrong
,本质是新值retain,旧值release
weak
在底层调用objc_initWeak
4. imp & SEL
SEL:方法编号,相当于书本目录的名称
IMP:函数指针地址,相当于书本目录的页码
1:首先需要找到书本的什么内容 (sel 目录里面的名称)
2:通过名称找到对应的本⻚码 (imp)
3:通过⻚码去定位具体的内容
5. 成员变量、实例变量、属性区分
-
- 定义在{}号中的除去基本
数据类型int float ....
等,其他类型的变量都叫做实例变量
。
实例变量+基本数据类型变量=成员变量
- 定义在{}号中的除去基本
-
- 成员变量
不能外部访问
,如需访问可以自定义setter getter方法
或者将变量定义为属性
- 成员变量
@interface ViewController : UIViewController
@property (nonatomic, copy) NSString *string;
@end
-
如果
{ NSString *string; }
并且@synthesize string;
则不会自动生成_string实例变量,通过string和self.string获取变量; -
如果
{ NSString *_string; }
并且@synthesize string;
则_string与self.string不是同一个变量,string与self.string同一个变量; -
如果
@synthesize string;
则不会自动生成_string实例变量,通过string和self.string获取变量;