什么是单例?数组
一个类只容许有一个实例,在整个程序中须要屡次使用,共享同一份资源的时候,就能够建立单例,通常封装成工具类使用,苹果封装成单例经常使用的有 UIApplication
,NSUserDefaults
,NSNotificationCenter
,NSFIleManager
等等。工具
我之前的写法 (不严谨的写法)post
// Singleton.h @interface Singleton : NSObject + (instancetype)sharedInstance; @end // Singleton.m static Singleton *_instance = nil; @implementation Singleton +(instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[Singleton alloc] init]; }); return _instance; } @end
这不算真正意义上的单例,不能保证全局的惟一性,由于类方法和 [ [Class alloc] init ] 方法建立的单例内存地址可能不同,全部不严谨。spa
下面举个栗子🌰code
Singleton *singOne = [Singleton sharedInstance]; Singleton *singTwo = [Singleton sharedInstance]; Singleton *singThere = [Singleton new]; Singleton *singFour = [[Singleton alloc] init]; NSLog(@"singOne:-> %@",singOne); NSLog(@"singTwo:-> %@",singTwo); NSLog(@"singThere:-> %@",singThere); NSLog(@"singFour:-> %@",singFour);
这时我看查看一下控制台输出的信息对象
2018-02-07 10:46:25.024988+0800 Markdown[2056:67507] singOne:-> <Singleton: 0x604000001a00> 2018-02-07 10:46:25.025222+0800 Markdown[2056:67507] singTwo:-> <Singleton: 0x604000001a00> 2018-02-07 10:46:25.025372+0800 Markdown[2056:67507] singThere:-> <Singleton: 0x6040000019a0> 2018-02-07 10:46:25.025646+0800 Markdown[2056:67507] singFour:-> <Singleton: 0x604000001a10>
结果很明显, [Singleton sharedInstance]
类方法建立出来单例singOne
和 singTwo
的内纯地址是同样的,说明单例建立对了,可是看到new
和 alloc init
建立的singThere
和 singFour
的内存地址不同,同时也与singOne
和 singTwo
的地址不同.内存
百度一下还真有这类的帖子和博客,咱们主要的问题就是保证单例的惟一性,避免不当心用实例方法建立单例,全部应该保证alloc init
、new
、copy
方法建立的单例的的惟一性。资源
在建立对象的时候主要分这么两步 alloc (申请内存)init(初始化)开发
拷贝对象也是同样的,覆写copyWithZone方法,而后在方法中去调用类方法,返回单例对象。(在覆写copyWithZone方法以前别忘记了签署NSCopying协议)get
下面修改一下 Singleton.m
参考:iOS-单例模式简单使用
// Singleton.m static Singleton *_instance = nil; @implementation Singleton +(instancetype)sharedInstance { if (_instance == nil) { _instance = [[super alloc]init]; } return _instance; } + (instancetype)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } - (id)copyWithZone:(NSZone *)zone{ return _instance; } - (id)mutableCopyWithZone:(NSZone *)zone{ return _instance; }
看一下控制台输出的结果:
2018-02-07 11:20:46.993693+0800 Markdown[2374:88765] singOne:-> <Singleton: 0x604000001990> 2018-02-07 11:20:46.993906+0800 Markdown[2374:88765] singTwo:-> <Singleton: 0x604000001990> 2018-02-07 11:20:46.994040+0800 Markdown[2374:88765] singThere:-> <Singleton: 0x604000001990> 2018-02-07 11:20:46.994146+0800 Markdown[2374:88765] singFour:-> <Singleton: 0x604000001990>
很明显,改过 Singleton.m
后Singleton
类方法的类方法sharedInstance
和 实例方法 alloc init
的方法建立的单例内存地址同样了,是否是有点小喜悦。
哪一个单例里面没有几个属性,最少也得有一个吧,要否则我要这铁(dan)棒(li)有何用。
这就加几个属性试试。
Singleton *singOne = [Singleton sharedInstance]; SingOne.array = @[@"1",@"2",@"3"]; Singleton *singTwo = [Singleton sharedInstance]; SingOne.array = @[@"4",@"5",@"6"]; Singleton *singThere = [Singleton new]; SingThere.array = @[@"7",@"8",@"9"]; Singleton *singFour = [[Singleton alloc] init]; SingFour.array = @[@"0",@"0",@"0"]; NSLog(@" singOne:-> %@ , %p , %@ ",singOne,singOne.array,singOne.array); NSLog(@" singTwo:-> %@ , %p , %@ ",singTwo,singTwo.array,singTwo.array); NSLog(@"singThere:-> %@ , %p , %@ ",singThere,singThere.array,singThere.array); NSLog(@" singFour:-> %@ , %p , %@ ",singFour,singFour.array,singFour.array);
如今看看结果
array
属性地址惟一,数组内容也惟一,知足标准。
2018-02-07 11:48:39.843225+0800 Markdown[2804:110175] singOne:-> <Singleton: 0x60000003ec60> , 0x600000445250 , ( 0, 0, 0 ) 2018-02-07 11:48:39.843439+0800 Markdown[2804:110175] singTwo:-> <Singleton: 0x60000003ec60> , 0x600000445250 , ( 0, 0, 0 ) 2018-02-07 11:48:39.843589+0800 Markdown[2804:110175] singThere:-> <Singleton: 0x60000003ec60> , 0x600000445250 , ( 0, 0, 0 ) 2018-02-07 11:48:39.843713+0800 Markdown[2804:110175] singFour:-> <Singleton: 0x60000003ec60> , 0x600000445250 , ( 0, 0, 0 )
感谢以上两位博主的文章,借鉴作了一份单例的笔记,记录开发中的问题并解决问题。