Date
Nov. 22nd, 2024
 
2024年 10月 22日

Post: iOS 入门 016: 单例模式及其实现

iOS 入门 016: 单例模式及其实现

Published 12:04 Apr 17, 2012.

Created by @ezra. Categorized in #Programming, and tagged as #iOS.

Source format: Markdown

Table of Content

单例模式及其实现

  • 步骤

    • 提供全局访问方法,公认的格式 shared+类型

    • 有一个静态全局变量,保证对象的实例保存在静态区,并且不需要关心释放 的问题

    • 重写allocWithZone方法,能够保证对象只被实例化一次!

      • 需要包含dispatch_once:保证对象只被分配一次内存空间
    • 实现shared方法

      • 需要包含dispatch_once:保证对象只被初始化一次

eg.h

#import <Foundation/Foundation.h>
@interface SoundTools : NSObject <NSCopying>
// 全局的访问方法
+ (instancetype)sharedSoundTools;
@end

eg.m

@interface SoundTools()
@property (nonatomic, assign) int count;
@end

@implementation SoundTools
static id instance;

// 所有对象的内存分配,最终都会调用到此方法
// 把这个方法搞定,就能实现单例!
+ (instancetype)allocWithZone:(struct _NSZone *)zone {

    // 问题:这种方式不是线程安全的
    // 解决方法1:增加互斥锁
//    @synchronized (self) {
//        if (instance == nil) {
//            instance = [super allocWithZone:zone];
//        }
//    }
    // 其他解决办法?dispatch_once,执行一次,线程安全!
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (instance == nil) {
            instance = [super allocWithZone:zone];
        }
    });
    return instance;
}

+ (instancetype)sharedSoundTools {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 使用shared方法只能做一次初始化!
        instance = [[self alloc] init];
    });
    ⏎ instance;
}

//------------- 以上部分是面试的时候,需要手写单例的代码------
- (id)copyWithZone:(NSZone *)zone {
    ⏎ instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _count = 10;
        NSLog(@"初始化 %d", _count);
    }
    ⏎ self;
}
@end

MRC中的单例的实现

  • 先参考ARC中单例的实现部分

eg.m

#pragma mark - MRC模式中需要增加的代码
- (oneway void)release {
    // 原本的程序是做计数-1
}

- (instancetype)retain {
    return instance;
}

- (instancetype)autorelease {
    return instance;
}

- (NSUInteger)retainCount {
    // retainCount返回最大整数,此方法可以不重写
    // 出处 limits.h ULONG_MAX 宏可以自行根据运行的CPU架构调整整数的长度
    return ULONG_MAX;
}

抽取单例宏

Singleton.h

#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]; \
        } \
    }); \
    ⏎ instance; \
} \
+ (instancetype)shared##className { \
    static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
        instance = [[self alloc] init]; \
    }); \
    ⏎ instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
    ⏎ instance; \
} \
- (oneway void)release {} \
- (instancetype)retain {⏎ instance;} \
- (instancetype)autorelease {⏎ instance;} \
- (NSUInteger)retainCount {⏎ ULONG_MAX;}
#endif
// 提示末尾一行不要有 \

eg.h

#import <Foundation/Foundation.h>
#import "Singleton.h"
@interface SoundTools : NSObject <NSCopying>
// 全局的访问方法
//+ (instancetype)sharedSoundTools;
singletonInterface(SoundTools);
@end

eg.m

#import "SoundTools.h"
@interface SoundTools()
/** 声音的数量 */
@property (nonatomic, assign) int count;
@end

@implementation SoundTools
static id instance;
singletonImplementation(SoundTools);
#pragma mark - MRC 部分代码
- (instancetype)init
{
    self = [super init];
    if (self) {
        _count = 10;
        NSLog(@"初始化 %d", _count);
    }
    return self;
}
@end
Pinned Message
HOTODOGO
The Founder and CEO of Infeca Technology.
Developer, Designer, Blogger.
Big fan of Apple, Love of colour.
Feel free to contact me.
反曲点科技创始人和首席执行官。
开发、设计与写作皆为所长。
热爱苹果、钟情色彩。
随时恭候 垂询