单例01

1.

Code:

@interface SAMNetworkingTool : NSObject

+ (instancetype)shareNetworkingTool;

@end

@implementation SAMNetworkingTool

static id instance;

// 因为历史遗留问题,每次调用alloc的时候都会先调用allocWithZone

+ (instancetype)allocWithZone:(struct _NSZone *)zone{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

// 这个函数在该程序中只执行一次

instance = [super allocWithZone:zone];

});

return instance;

}

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

return instance;

}

+ (instancetype)shareNetworkingTool{

return  [[self alloc] init];

}

@end

Test:

- (void)viewDidLoad {

[super viewDidLoad];

for (int i = 0; i< 10; i++) {

SAMNetworkingTool *tool  = [SAMNetworkingTool shareNetworkingTool];

NSLog(@"%@",tool);

}

[self performSelectorInBackground:@selector(testDemo) withObject:nil];

}

- (void)testDemo {

puts("-----");

for (int i = 0; i< 10; i++) {

SAMNetworkingTool *tool  = [SAMNetworkingTool shareNetworkingTool];

NSLog(@"%@",tool);

}

}

单例实现:(两种方式:互斥锁(@synchronized(self))和一次性代码(dispatch_once));

2.1互斥锁 @synchronized(self):

<1>.在 .m 文件中保留一个全局的 static 的实例.

static id _instance;

<2>.重写若干方法(allocWithZone:和 copyWithZone:)并提供一个类方法让外界访问唯一的实例.

//(1)重写 allocWithZone:方法,在这里创建唯一的实例(注意线程安全). //alloc 内部都会调用这个方法.

+(instancetype)allocWithZone:(struct _NSZone *)zone {

if (_instance == nil) { // 防止频繁加锁

@synchronized(self) {

if (_instance == nil) { // 防止创建多次

_instance = [super allocWithZone:zone];

}

}

}

return _instance;

}

//(2)重写 copyWithZone:方法.

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

{

return _instance;

}

//(3)提供1个类方法让外界访问唯一的实例

+(instancetype)shareSingleton

{

if (!_instance) { // 防止频繁加锁

@synchronized(self){

if (!_instance) { // 防止创建多次

_instance = [[self alloc] init];

}

}

}

return _instance;

}

2

一次性代码(dispatch_once):

<1>.在 .m 文件中保留一个全局的 static 的实例.

static id _instance;

<2>.重写若干方法(allocWithZone:和 copyWithZone:)并提供一个类方法让外界访问唯一的实例.

//(1)重写 allocWithZone:方法,在这里创建唯一的实例(注意线程安全).

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

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instace = [super allocWithZone:zone];

});

return _instace;

}

//(2)重写 copyWithZone:方法.

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

{

return _instance;

}

//(3)提供1个类方法让外界访问唯一的实例

+ (instancetype)shareSingleton

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instace = [[self alloc] init];

});

return _instace;

}

注意:在 ARC 和 MRC 中单例的实现方式略有不同. MRC 下单例的实现比 ARC 多了几个内存管理的方法:

MRC 中增加如下方法的实现:

- (instancetype)retain { return self; }

- (NSUInteger)retainCount { return 1; }

- (oneway void)release {}

- (instancetype)autorelease { return self; }

3.判断当前环境(ARC/MRC)

#if __has_feature(objc_arc)

// ARC

#else

// MRC

#endif

注意:,单例最好只提供一个创建单例的方式

如 创建一个访问网络的管理类

#import "AFHTTPSessionManager.h"

@interface SAMNetworkingTool : AFHTTPSessionManager

+ (instancetype)shareNetWorkingManager;

@end

#import "SAMNetworkingTool.h"

@implementation SAMNetworkingTool

static id _instance;

+ (instancetype)shareNetWorkingManager{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

NSURLSessionConfiguration *sett = [NSURLSessionConfiguration defaultSessionConfiguration];

sett.timeoutIntervalForRequest = 15;

NSURL *baseUrl = [NSURL URLWithString:@"http://c.m.163.com/nc/"];

_instance = [[SAMNetworkingTool alloc] initWithBaseURL:baseUrl sessionConfiguration:sett];

});

return _instance;

}

对外只提供一种方式创建该对象,,

时间: 2024-12-06 07:26:09

单例01的相关文章

Effective java 第2版 - 笔记(01) 单例(Singleton)的枚举(enum)实现

直接上代码: 1 public enum Boss { 2 3 INSTANCE; 4 5 private String name; 6 7 public void doSomeThing() { 8 System.out.println(name + " is doing something now..."); 9 } 10 11 public String getName() { 12 return name; 13 } 14 15 public void setName(Stri

iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)

iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notification方式:3.block方式:4.UserDefault或者文件方式:5.单例模式方式:6.通过设置属性,实现页面间传值 在iOS开发中,我们经常会遇到页面间跳转传值的问题,现归纳总结一下: 情况1:A页面跳转到B页面 方法: 在B页面的控制器中,编写对应的属性,在A页面跳转到B页面的地方,给

IOS_地图_定位_天气预报_Block回调_单例

H:/1021/00_block回调.h /* 通过block回调 定义block代码块,目的是解析完成之后调用 返回值是 void 参数是 数组,里面的每个成员是一个NSString*/ typedef void(^WeatherFinishedBlock)(NSArray *dataList); @interface WeatherXMLPaser : NSObject // 解析器解析数据,参数1是要解析的数据,参数2是解析完毕回调的代码块 - (void)parserWeatherDat

OC学习-单例设计模式的理解、案例和简单总结

单例模式,就是一个类始终只有一个实例,不管如果copy还是retain还是alloc等等,都只有一个实例.为什么?有什么好处? 简单来说: a:有的东西只能有一个,那就必须用单例: b:单例的好处就是不会有多余的实例,所以节约内存: c:因为只有一个单例,所以易于管理多线程对它的访问. d:其他的原因……省略 我们创建一个单例的User类,然后生成一个user1对象,再把这个对象进行copy.retain这些,再看看它们是否是同一个实例,还是被创建出多个实例? (1)User.h view so

iOS页面间传值的五种方式总结(Delegate/NSNotification/Block/NSUserDefault/单例)

iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notification方式:3.block方式:4.UserDefault或者文件方式:5.单例模式方式:6.通过设置属性,实现页面间传值 在iOS开发中,我们经常会遇到页面间跳转传值的问题,

数据持久化、单例、重载【添加对不可访问的成员的操作】、魔术方法、类常量、static关键字对self的补充【静态延迟绑定实现$this的效果】、参数类型约束【参数前加类名】、遍历【iterator接口】、快速排序

1.数据持久化过程[传输(例如表单提交或php交互mysql)和保存过程] 使用的是字符串形式的流数据. 数据流就是为了传输[按照序列的形式进行传输] [http://baike.baidu.com/link?url=0MtUQMhFzc_EwJc09rXZV8KlfOL4jis6XNbRfmGA3rQhDcGwOp8togLVQjXBV34M] 所以将其他类型数据转化为字符串的过程也是序列化的过程 [这个概念和图片.视频的流媒体的区别?] [注意点] 另外mysql中sql语句中的某些关键词为

单例类多线程

作为设计模式理论中的Helloworld,相信学习java语言的人,都应该听说过单例模式.单例模式作为对象的一种创建模式,它的作用是确保某一个类在整个系统中只有一个实例,而且自行实例化并向整个系统提供这个实例. 由此可见,单例模式具有以下的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一的实例. 单例类必须给所有其他对象提供这一实例. 由于Java语言的特点,使得单例模式在Java语言的实现上有自己的特点.这些特点主要表现在单例类如何将自己实例化. 饿汉式单例类 饿汉式单例类是在Ja

js21---单体(单例)模式

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Unt

单例还是静态?

说实话...iOS开发的学习中,我从未使用过单例,也是最近才开始思考单例这个问题, 以前遇到这种需求的时候都是直接一个静态过去解决全部,但是静态带来的后果就是不便于维护. 在http://www.blogjava.net/ITdavid/archive/2008/01/22/176939.html看到了这么一段话 # re: 采用单例模式还是静态方法? 2008-01-27 07:56 小雨 这个问题我也思考了一段时间. 我现在的想法是这样的:如果一个类不需要扩展,就使用静态方法类,当然也可以使