单例模式 - GCD 、兼容ARC和MRC

时间:2022-07-20 05:18:18


单例模式 - GCD、兼容ARCMRC



单例模式的作用:

1,可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问

2,从而方便地控制了实例个数,并节约系统资源


单例模式的使用场合:

在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)


单例模式在ARC\MRC环境下的写法有所不同,需要编写2套不同的代码

可以用宏判断是否为ARC环境

#if __has_feature(objc_arc)

//ARC

#else

//MRC

#endif



在游戏中,音乐在不同的场景可能相同,我们应该只要创建一份,这时候我们就应该使用单例模式,可以节省内存;

ARC环境下,实现单例模式:  代码如下:


要使得他们alloc init一份,就可以使用GCDdispatch_once,还可以保证线程安全;

#import "HMAudioTool.h"


@interface HPAudioTool()

@end


@implementation HPAudioTool

//// 定义一份变量(整个程序运行过程中,只有1)

static id _instance;


- (id)init

{

    if (self = [super init]) {

        static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            //加载资源

            

        });

    }

    return self;

}

/**

 *  重写这个方法 :控制内存内存

 */

+ (id)allocWithZone:(struct _NSZone *)zone

{

    // 里面的代码永远只执行1

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [super allocWithZone:zone];

    });

    

    //返回对象

    return _instance;

}


+ (instancetype)sharedAudioTool

{

    // 里面的代码永远只执行1

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [[self alloc] init];

    });

    

    //返回对象

    return _instance;

}


+ (id)copyWithZone:(struct _NSZone *)zone

{

    return _instance;

}


@end



那么在MRC中呢?那当然就要考虑内存的释放了;必须要release了;

然而在release方法中,会调用[super release];

还有autorelease,retain,retainCount,copyWithZone;都得保证调用一次;

代码如下:


@interface HPAudioTool()

@end


@implementation HPAudioTool

//// 定义一份变量(整个程序运行过程中,只有1)

static id _instance;


- (id)init

{

    if (self = [super init]) {

        static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            //加载资源

            

        });

    }

    return self;

}

/**

 *  重写这个方法 :控制内存内存

 */

+ (id)allocWithZone:(struct _NSZone *)zone

{

    // 里面的代码永远只执行1

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [super allocWithZone:zone];

    });

    

    //返回对象

    return _instance;

}


+ (instancetype)sharedAudioTool

{

    // 里面的代码永远只执行1

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [[self alloc] init];

    });

    

    //返回对象

    return _instance;

}


+ (id)copyWithZone:(struct _NSZone *)zone

{

    return _instance;

}

- (oneway void)release

{

    

}


- (id)autorelease

{

    return _instance;

}


- (id)retain

{

    return _instance;

}


- (NSUInteger)retainCount

{

    return 1;

}


+ (id)copyWithZone:(struct _NSZone *)zone

{

    return _instance;

}

@end



当然我们在使用过程中,我们可以把这些代码写成宏,使用起来方便,便于修改;

为了兼容ARCMRC,我们可以将代码合并如下:


// ## :连接字符串和参数

#define singleton_h(name) + (instancetype)shared##name;


#if __has_feature(objc_arc) // ARC


#define singleton_m(name) \

static id _instance; \

+ (id)allocWithZone:(struct _NSZone *)zone \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instance = [super allocWithZone:zone]; \

}); \

return _instance; \

} \

\

+ (instancetype)shared##name \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instance = [[self alloc] init]; \

})\

return _instance; \

} \

+ (id)copyWithZone:(struct _NSZone *)zone \

{ \

return _instance; \

}


#else //ARC


#define singleton_m(name) \

static id _instance; \

+ (id)allocWithZone:(struct _NSZone *)zone \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instance = [super allocWithZone:zone]; \

}); \

return _instance; \

} \

\

+ (instancetype)shared##name \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instance = [[self alloc] init]; \

}); \

return _instance; \

} \

\

- (oneway void)release \

{ \

\

} \

\

- (id)autorelease \

{ \

return _instance; \

} \

\

- (id)retain \

{ \

return _instance; \

} \

\

- (NSUInteger)retainCount \

{ \

return 1; \

} \

\

+ (id)copyWithZone:(struct _NSZone *)zone \

{ \

return _instance; \

}


#endif

然后大家直接可以拷贝走,直接拿去调用;