iOS單例模式(面試必考)

​# 單例模式(面試必考)面試

1. 單例模式的做用

  • 能夠保證在程序運行過程,一個類只有一個實例,並且該實例易於供外界訪問
  • 從而方便地控制了實例個數,並節約系統資源

2. 單例模式的使用場合

  • 在整個應用程序中,共享一份資源(這份資源只須要建立初始化1次)

3. ARC中,單例模式的實現

  • 1.在.m中保留一個全局的static的實例
static id _instance;
  • 2.重寫allocWithZone:方法,在這裏建立惟一的實例(注意線程安全)
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}
  • 3.提供1個類方法讓外界訪問惟一的實例
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
  • 4.實現copyWithZone:方法
- (id)copyWithZone:(struct _NSZone *)zone
{
    return _instance;
}

4.ARC中完整版(GCD)

static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:zone] init]; // 記住這兒是super,不能用self
    });

    return _instance;
}

+ (instancetype)sharedPerson
{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

// copyWithZone方法的前提是必須先有一個對象
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
  • 在實際開發中,一個應用程序可能有多個對象是單例對象,此時咱們應該把單例抽成一個宏放在一個單獨的.h文件中,千萬不能用繼承
    • 其中\表示此行跟下面一行是一塊兒的
    • ## 表示後面是參數
    • 此時,註釋只能在上面,在右邊註釋會報錯的
// .h文件中的聲明
#define SLInstanceH(name)  + (instancetype)shared##name;
// .m文件的實現
#define SLInstanceM(name) static id _instance; \
\
+ (instancetype)allocWithZone:(struct _NSZone *)zone\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [[super allocWithZone:zone] init];\
    });\
    return _instance;\
}\
\
+ (instancetype)shared##name\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [[self alloc] init];\
    });\
    return _instance;\
}\
\
- (id)copyWithZone:(NSZone *)zone\
{\
    return _instance;\
}
  • 使用宏的時候
  • 在.m文件中
#import <Foundation/Foundation.h>
#import "SLSharedInstance.h"  // 導入,定義了宏的.h文件

@interface SLPerson : NSObject<NSCopying>
SLInstanceH(Person)  // 傳入單例的對象
@end
  • 在.h文件中
#import "SLPerson.h"

@implementation SLPerson
SLInstanceM(Person)
@end

5. 單例模式(常規作法,非GCD)

  • 必定要加互斥鎖,否則會有線程安全問題
#import "SLPerson.h"

@implementation SLPerson
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    @synchronized(self){ // 必定要加互斥鎖,否則會有線程安全問題
        if (_instance == nil) {
            _instance = [[super allocWithZone:zone] init];
        }
    }
    return _instance;
}
+ (instancetype)sharedPerson
{
    @synchronized(self){
        if (_instance == nil) {
            _instance = [[self alloc] init];
        }
    }
    return _instance;
}

// 要有對象才能進行copy
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
@end
相關文章
相關標籤/搜索