OC中的单例模式

单例模式在iOS开发中可能算是最常用的模式之一了.(废话不多说, 直接进入主题)

1. 什么是单例模式?

 a.整个程序运行期间, 永远只分配一块内存来创建对象

 b.最好提供一个类方法,返回内部唯一的一个对象(一个实例)


2. 该怎样去写?

2.1. 一般情况下, 我们可以这样写:

注意:当我们调用sharedInstance方法获取到的对象的确是相同的, 但是当我们通过allocinit来构造对象的时候, 得到的对象却不一样. 所以这样写是有缺陷的.

@interface Singleton : NSObject
+ (instancetype)shareInstance ;
@end
 
@implementation Singleton
 
static Singleton *_instance = nil;
 
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    }) ;
     
    return _instance ;
}


小结: 使用上面的这种方法, 导致我们通过不同的途径去创建得到不同的对象, 显然不行, 我们设计单例模式, 就必须要确保对象的唯一性, 所以我们就需要对alloc/init/copy等等方法进行过滤.
  创建对象时会进行alloc(申请内存)init(初始化)俩个步骤, 而调用alloc方法时, OC内部会调用allocWithZone来申请内存,  我们想要确保对象是唯一的, 所以我们得重写这些方法. 
ARC中: 需要重写 init方法, allocWithZone方法, copyWithZone方法:
static id _instance;
- (id)init
{
    if (self = [super init]) {
        // 加载资源
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
        });
    }
    return self;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
    return _instance;
}

而在MRC中, 因为需要手动释放内存, 但是如果真的释放了, 下次创建对象就会失败, 所以得多重写4个方法:
- (oneway void)release 
{ 

} 

- (id)autorelease 
{ 
    return _instance; 
} 

- (id)retain 
{ 
    return _instance; 
} 

- (NSUInteger)retainCount 
{ 
    return 1; 
} 

+ (id)copyWithZone:(struct _NSZone *)zone 
{ 
    return _instance; 
}

这样就可以了, 但是如果经常用到, 而且让我们不用关心ARC或MRC环境, 最好还是写个头文件, 将这些代码用一个宏来表示.
在这之前, 先了解以下 :
 a. 可以用宏来判断当前的环境(ARC or MRC)
#if __has_feature(objc_arc)
#else
//MRC
#endif
b. 宏后面如果要表示多行, 则可以跟上 \ , 即表明有 \ 标记的都是属于这个宏的, 但是注意最后一行不能加上 \ .
c. 宏里面, 可以用## 来拼接参数

下面是头文件:(Singleton.h)
// ## : 连接字符串和参数
#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; \
}

使用方法:
//.h类
//引入这个宏文件
#import "Singleton.h"
@interface Object : NSObject
singleton_h(name)
@end

//.m类
@implementation Object
singleton_m(name)
@end





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值