你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS技巧綜合 >> 單例實現(單例宏)

單例實現(單例宏)

編輯:IOS技巧綜合
[摘要]本文是對單例實現(單例宏)的講解,對學習IOS蘋果軟件開發有所幫助,與大家分享。

一、什麼是單例

單例就是,一個類,每次創建都是同一個對象。也就是說只能實例化一次。

二、如何保證每次創建都是同一個對象

創建一個對象歸根揭底都會經過一個途徑,alloc方法(alloc方法會調用allocWithZone:)。因此只要保證alloc方法只會調用一次,且保證線程安全,然後把此對象放在靜態區。以後不管是創建對象還是copy對象都直接返回靜態區的對象。

三、注意點

靜態全局變量不需要考慮釋放的問題(適用於MRC),解決線程安全問題可以用互斥鎖或者GCD,後者更好。

也可設置不讓對象重復初始化,即讓初始化方法只能執行一次。

四、具體實現代碼如下

@implementation myManager
static id instance;

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    // 1、互斥鎖
//        @synchronized (self) {
//            if (instance == nil)
//            {
//                instance = [super allocWithZone:zone];
//            }
//        }
    
    // 2、GCD,只執行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (instance == nil)
        {
            instance = [super allocWithZone:zone];
        }
    });
    return instance;
}

+ (instancetype)sharedSoundTools
{
    instance = [[self alloc] init];
    return instance;
}

- (id)copyWithZone:(NSZone *)zone
{
    return instance;
}

#pragma mark - MRC 部分代碼
- (oneway void)release
{
    // 什麼都不做
}

- (instancetype)retain
{
    // 本想什麼都不做,但它要返回值
    return instance;
}

- (instancetype)autorelease
{
    return instance;
}

- (NSUInteger)retainCount
{
    // 此處防治有人不明就裡的粗暴釋放對象,比如while循環
    return ULONG_MAX;
}

- (instancetype)init
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        self = [super init];
        if (self)
        {
            self.age = 10; // 只是舉個例子,只初始化一次,可以不設置
        }
    });
    return self;
}

@end

五、單例宏

以下代碼寫在單獨singleton.h文件裡,使用時直接包含.h頭文件。

使用方法,.h文件:singletonInterface(myManager);

.m文件:singletonImplementation(myManager);

抽取代碼如下:

#define singletonInterface(className)          + (instancetype)shared##className;

#if __has_feature(objc_arc)
// 以下是ARC版本
#define singletonImplementation(className) \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        if (instance == nil) { \
            instance = [super allocWithZone:zone]; \
        } \
    }); \
    return instance; \
} \
+ (instancetype)shared##className { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        instance = [[self alloc] init]; \
    }); \
    return instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
    return instance; \
}
#else
// 以下是MRC版本
#define singletonImplementation(className) \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        if (instance == nil) { \
            instance = [super allocWithZone:zone]; \
        } \
    }); \
    return instance; \
} \
+ (instancetype)shared##className { \
    static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
        instance = [[self alloc] init]; \
    }); \
    return instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
    return instance; \
} \
- (oneway void)release {} \
- (instancetype)retain {return instance;} \
- (instancetype)autorelease {return instance;} \
- (NSUInteger)retainCount {return ULONG_MAX;}
#endif

// 提示末尾一行不要有 \
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved