單例對象的創(chuàng)建方式
單例.h 文件的實現(xiàn)
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NBNetworkTools : NSObject
// 創(chuàng)建單例對象
+ (instancetype)sharedInstance;
// 銷毀單例對象
- (void)dellocInstance;
// 用戶名
@property (nonatomic,copy) NSString *username;
// 密碼
@property (nonatomic,copy) NSString *password;
@end
NS_ASSUME_NONNULL_END
單例的.m 文件的實現(xiàn)
#import "NBNetworkTools.h"
@implementation NBNetworkTools
static NBNetworkTools *sharedInstance = nil;
static dispatch_once_t onceToken;
+ (instancetype)sharedInstance {
dispatch_once(&onceToken, ^{
// 使用super 調(diào)用父類等 allocWithZone再登,避免循環(huán)引用
// 因為重寫了 allocWithZone 返回的是 [self sharedInstance]端铛, 如果調(diào)用了 [self allocWithZone], 就會出現(xiàn)循環(huán)調(diào)用的問題,規(guī)避循環(huán)引用使用 super 進(jìn)行初始化
sharedInstance = [[super allocWithZone:NULL]init];
});
return sharedInstance;
}
// 【必不可少】重寫 allocWithZone 方法
// 因為不使用 sharedInstance 進(jìn)行創(chuàng)建對象的情況已慢,也是有可能的
// 比如使用 alloc 進(jìn)行創(chuàng)建匿垄, alloc 會調(diào)用 allocWithZone ,所以重寫 allocWithZone,在內(nèi)部手動調(diào)用 [self sharedInstance];
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 【必不可少】當(dāng)單例被 copy
// 外界有可能會對當(dāng)前實例進(jìn)行copy操作來創(chuàng)建一個對象鲫售,要保證一個對象在App生命周期內(nèi)永遠(yuǎn)只能被創(chuàng)建一次,我們還需要重寫 copyWithZone 方法
// 直接將 self 返回就可以了
- (id)copyWithZone:(nullable NSZone *)zone {
return self;
}
// 銷毀單例對象
- (void)dellocInstance {
// 設(shè)置為0该肴,GCD會認(rèn)為它從未執(zhí)行過情竹,這樣才能保證下次調(diào)用 shareInstance 的時候,再次創(chuàng)建對象
onceToken = 0;
sharedInstance = nil;
}
單例對象的銷毀【GCD創(chuàng)建的方式】
使用單例對象的時候沙庐,如果我們暫時不用這個對象鲤妥,同時想釋放單例占用的內(nèi)存空間,所以我們需要把它銷毀掉拱雏,用的時候在創(chuàng)建出來棉安,那怎么做呢?
上面的代碼是包含這部分功能的铸抑,操作的方式就是在銷毀的方法里面:把 onceToken = 0; 設(shè)置為0贡耽,此時我們的GCD就會認(rèn)為這個block沒有執(zhí)行過,就會再次執(zhí)行Block內(nèi)的代碼
- 可以通過打印觀察 onceToken 的值的變化鹊汛,就可以發(fā)現(xiàn)了
- 下面是銷毀的代碼
// 銷毀單例對象
- (void)dellocInstance {
// 設(shè)置為0蒲赂,GCD會認(rèn)為它從未執(zhí)行過,這樣才能保證下次調(diào)用 shareInstance 的時候刁憋,再次創(chuàng)建對象
onceToken = 0;
sharedInstance = nil;
}