OC中的单例模式

释放双眼,带上耳机,听听看~!

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

1. 什么是单例模式?

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

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

 

2. 该怎样去写?

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

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

 

@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

 

人已赞赏
iOS文章

ios自定义UICollectionViewLayout(二) ----StackLayout&CircleLayout

2020-5-18 5:18:05

iOS文章

去掉警告--->; ld: warning: directory not found for option

2020-5-18 6:33:01

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索