1. Lazy 懒加载
1.1 创建
swift
中懒加载
是使用Lazy
进行修饰
- 必须是
var
(可变存储属性),不可以是let
(不可变属性),也不能是option
(可选值)。
class HTPerson {
// 懒加载属性
lazy var name: String = "ht"
}
初始
时,没有值
。
首次访问
后,有值
- 所以
Lazy
修饰的属性,具备延时加载
功能。(首次访问
时才加载
)
1.2 大小
-
image懒加载属性
的大小
,与本身属性
大小不同
:
swift中int
(64位系统)原本8字节
,但lazy修饰后
,就变成16字节
1.3 懒加载的本质
-
懒加载属性,创建时,是
可选值
。但是在首次访问(getter)时,进行初始赋值,返回非可选类型的值。 -
懒加载是
线程不安全
的。读写未加锁
,多线程同时访问(getter)时,可能多次赋值
Q: 为何lazy修饰的Int属性是16字节:
- 因为
lazy修饰
的属性,会变成可选类型
。
(option
: 可选类型。本质是枚举
,值类型
)
包含some<Int>
和none
两个枚举类型。其中none
是0x0
。打印![image](https://img.haomeiwen.com/i12857030/bbe04395faff43ee.png?imageMogr2/auto-orient/strip|imageView2/2/w/480)
- 其中:
none
占1字节
,some<Int>
占8字节
。所以实际大小
(size)为9字节
。- 对外遵循
align8
(8字节对齐)原则,系统
会开辟16字节空间
(8的倍数)来存储真实大小
为9字节
的数据
(align8原则
:为了避免五花八门
的空间大小
,增加系统读取数据
的困难性
。所以统一
以8字节
为一个单位
,进行一段一段
的截取
,提高读取效率
。)
lazy总结
lazy
必须修饰var
(可变
类型)存储
属性,- 必须有
默认初始值
,但初始值会延迟
到首次加载
时赋值
。
(所以lazy修饰
的属性
,叫延迟存储属性
,也叫懒加载
属性)延迟存储属性
是线程不安全
的(可能多次赋值)延迟存储属性
影响实例对象
的大小
2. static 单例
Swift单例:
直接static创建,将init方法藏起来(private私有重写)。
class HJPerson {
// 创建单例对象
static let sharedInstance = HJPerson()
// 重写init方法,设为私有方法
private init(){}
}
-
swift源码
查看swift_once
,内部调用gcd
的dispatch_once_f
,创建单例
,线程安全
(内部有锁,读写安全)。
OC单例:
使用gcd创建,使用父类alloc初始化,拦截alloc,任何方式实例化,返回的都是单例对象。
@implementation HTPerson
static HTPerson *sharedInstance = nil;
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 不使用alloc方法,而是调用[[super allocWithZone:NULL] init]
// 重载allocWithZone基本的对象分配方法,所以要借用父类(NSObject)的功能处理底层内存分配
// 此时不管外部使用设么方式创建对象,最终返回的都是单例对象
sharedInstance = [[super allocWithZone:NULL] init] ;
});
return sharedInstance;
}
+(id)allocWithZone:(struct _NSZone *)zone {
return [HTPerson sharedInstance] ;
}
-(id)copyWithZone:(NSZone *)zone {
return [HTPerson sharedInstance] ;
}
-(id)mutablecopyWithZone:(NSZone *)zone {
return [HTPerson sharedInstance] ;
}
@end
网友评论