signal(單例)

signal(單例)

  • 1.1 概念

(1)單例模式

(1.1)在程序運行過程,一個類只有一個實例,而且該實例易于供外界訪問
(1.2)方便地控制了實例個數,并節約系統資源
(1.3)單例是不可以用繼承的,因為不能父類與子類共用一個全局變量

(2)使用場合

在整個應用程序中,共享一份資源(這份資源只需要創建初始化1次)
  • 1.2 實現通過單例(在ARC與MRC中均可執行)

(1)實現步驟

01 在類的內部提供一個static修飾的全局變量
02 重寫+allocWithZone方法,保證永遠都只為單例對象分配一次內存空間
03 提供一個類方法,方便外界訪問
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法
05 通過條件編譯判斷是否是ARC{__has_feature(objc_arc)},若是,則不再執行代碼,否則執行下述06-09代碼
06 重寫release方法
07 重寫retain方法
08 建議在retainCount方法中返回一個最大值
09 結束條件編譯

(2)如果在MRC中運行,需配置MRC環境知識

01 注意ARC不是垃圾回收機制,是編譯器特性
02 配置MRC環境:build setting ->搜索automatic ref->修改為NO

(3)相關代碼

//提供一個static修飾的全局變量,強引用著已經實例化的單例對象實例
static id _instance;

//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //使用GCD中的一次性代碼
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [[super allocWithZone:zone]init];
//    });

    //使用加鎖的方式,保證只分配一次存儲空間
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

//類方法,返回一個單例對象
+(instancetype)shareTools
{
     //注意:這里建議使用self,而不是直接使用類名Tools(考慮繼承)

    return [[self alloc]init];
}

//讓代碼更加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
//    return [[self class] allocWithZone:zone];
    return _instance;
}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}

#if __has_feature(objc_arc)
    //如果是ARC環境下
#else
    //如果是MRC環境下
//在MRC環境下,如果用戶retain了一次,那么直接返回instance變量,不對引用計數器+1
//如果用戶release了一次,那么什么都不做,因為單例模式在整個程序運行過程中都擁有且只有一份,程序退出之后被釋放,所以不需要對引用計數器操作
-(oneway void)release
{
}

-(instancetype)retain
{
    return _instance;
}

//慣用法,有經驗的程序員通過打印retainCount這個值可以猜到這是一個單例
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}
#endif

單例封裝宏

01 注意條件編譯的代碼不能包含在宏定義里面
02 宏定義的代碼只需要寫一次就好,之后直接拖到項目中用就OK
    #define SingleH(name) +(instancetype)share##name;

    #if __has_feature(objc_arc)
//ARC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [super allocWithZone:zone];\
    });\
    return _instance;\
}\
\
+(instancetype)share##name\
{\
    return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
    return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
    return _instance;\
}

#else
//mrc
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
    return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
    return MAXFLOAT;\
}

#endif
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ~ 寫在正文之前:文章轉移到翻這個墻中,希望繼續關注啦。(2017.11.5) signal(單例) 1.1 概念...
    fanzq_jianshu閱讀 407評論 0 0
  • 在iOS中有很多的設計模式,有一本書《Elements of Reusable Object-Oriented S...
    鄭明明閱讀 2,458評論 3 26
  • 單例模式的作用 可以保證在程序運行過程,一個類只有一個實例,而且該實例易于供外界訪問 從而方便地控制了實例個數,并...
    JonesCxy閱讀 385評論 0 0
  • 單例一般作為:工具類 單例命名:一般情況下如果一個類是單例,那么就要提供一個類方法用于快速創建單例對象,而且這個類...
    茉上心弦閱讀 1,787評論 0 15
  • 至簡書開啟記憶長河的主題,記憶深處有些東西就牽動心弦,兒時那些本來在記憶里已經零零碎碎,當時感覺再平常不過...
    緣柳閱讀 211評論 4 1