The implementation of the Singleton pattern in iOS is generally divided into two types: MRC and ARC+GCD
1.MRC (non-ARC)
Non-Arc single-instance implementations:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<span style="font-family: 仿宋; font-size: 15px;">#import <Foundation/Foundation.h> @interface NoARCSingleton:NSObject <span>//这个属性在后面调试有用处,而且也不要苦恼为什么是retain?不应该是copy么?请继续看下去,后面自然明白了<br></span>@property (nonatomic,retain) NSString *tempProperty; +(NoARCSingleton *)sharedInstance; @end @implementation NoARCSingleton static NoARCSingleton *sharedInstance = nil; //获取一个单例对象 + (BVNonARCSingleton *)sharedInstance {<br>//--------------------------------------------------<br> if (sharedInstance == nil) { sharedInstance = [[super allocWithZone:NULL] init]; } return sharedInstance;<br>//-------------------------------------------------- } //当第一次使用这个单例的时候,会调用这个init方法。 -(id)init { self = [super init]; if(self){ //通常在这里做一些相关的初始化任务 return self; } } //这个delloc方法永远都不会被调用,因为在程序的生命周期内,该单例都必须存在,该方法可以不用实现 -(void)delloc { [super dealloc]; }//通过返回当前的单例对象的方式来防止实例化新的对象 + (id)allocWithZone:(NSZone*)zone {<br> //线程相关的操作安全有</span>sharedInstance处理 |
?
| 1 2 3 4 5 6 7 |
<span style="font-family: 仿宋; font-size: 15px;">return [[self sharedInstance] retain]; } <br>Similarly, you do not want to generate multiple copies of the singleton, you must override <br>-(ID) Copywithzone: (Nszone *) zone {return self;} <br>// None of the operations in this method need a reference count (retain counter) <br>-(ID) retain {return self;} <br>//Replace the reference counter, which will never release this singleton <br>-(Nsuinteger) Retaincount {return nsuintegermax;} <br>// The method is empty-do not want the user to release the object. <br>-(OneWay void) release{}<br>//In addition to returning the single exception, do nothing. <br>-(ID) autorelease {return self;} <br> @end <br>//@synchronized's role is to create a mutex, Ensure that no other threads are modifying the Self object at this time. This is a lock token for objective-c, which prevents the self object from being accessed by other threads at the same time, and acts as a thread protection. Generally used in the case of common variables, such as singleton mode or the static variable of an operation class. <br>//Non-ARC implementation of the Singleton method is thread insecure, if there are multiple threads calling the <span>sharedinstance method at the same time to get an instance, <span> Sharedinstance takes 1-2s of time, the <span>nonarcsingleton init method may be called multiple times, that is, multiple threads may not be a singleton, and the way to solve this thread is unsafe by using <a href= "https://developer.apple.com/library/mac/#documentation/cocoa/conceptual/multithreading/threadsafety /threadsafety.html "target=" _blank "><span class=" Edui-filter-underline "> @synchronized </span></a><span> to create a mutex. <br>//<span> of course, this method does not guarantee that the invocation of all methods in this singleton is thread-safe </span><br></span></span></span ></span>//so the code between the lines above should be replaced with the following code @synchronized (self)</span> { if(sharedInstance == nil) { sharedInstance = [[super allocWithZone:NULL] init]; }<br>#param mark <span style="font-family: 仿宋; font-size: 15px;">-提醒:在iOS中,一般不建议使用非ARC来实现单例模式。更好的方法是使用ARC+GCD来实现。</span> |
How arc is implemented
?
| 1 2 3 4 5 6 7 |
<span style="font-family: 仿宋; font-size: 15px;">#import "ARCSingleton.h" @interface ARCSingleton : NSObject<br>//调试之用和上面的代码作用类似的,这里为什么用weak呢?请继续看下去~<br><span>@property ( nonatomic, weak) NSString *tempProperty;</span> + (ARCSingleton *)sharedInstance; @end @implementation ARCSingleton + (ARCSingleton *) sharedInstance {<br><span style="line-height: 1.5;"> staticARCSingleton *sharedInstance = nil ;</span></span> |
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span style="font-family: 仿宋; font-size: 15px;"> staticdispatch_once_t onceToken = 0; // 锁 dispatch_once (&onceToken, ^ { // 最多调用一次 sharedInstance = [[self alloc] init]; }); returnsharedInstance; } //当第一次使用这个单例时,会调用这个init方法 -(id)init { self = [super init]; if(self){ //初始化单例 } return self; } @end <br>//<span>在上面的代码中,调用</span><span class="edui-filter-underline"><a href="http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html" target="_blank">Grand Central Dispatch <br>(GCD)</a></span><span>中的</span><span class="edui-filter-underline"><a href="https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_once" target="_blank">dispatch_once</a></span><span>方法就可以确保ARCSingleton只被实例化一次。并且该方法是线程安全的,我们不用担心在不同的线程中,会获得不同的实例。(当然,该方法同样不能保证该单例中所有方法的调用都是线程安全的)。</span><br> </span> |
Of course, in the arc, without GCD can also be thread-safe, with the previous non-arc code using @synchronized, the following code:
?
| 1 2 3 4 5 6 7 8 9 |
<span style="font-family: 仿宋; font-size: 15px;"> // 不使用GCD,通过@synchronized @synchronized (self) { if(sharedInstance == nil) { sharedInstance = [[self alloc] init]; } } </span> |
To simplify the use of ARC+GCD to create a singleton, you can use the following macro
?
| 1 2 3 4 5 6 7 8 9 10 11 |
#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \static dispatch_once_t onceToken = 0; \ static id sharedInstance = nil; \dispatch_once(&onceToken, ^{ \sharedInstance = block(); \}); \return sharedInstance; \<br><span style="font-family: 仿宋; font-size: 15px;">//如果对于macro有问题的话强烈建议去脑补下猫神的文章http://onevcat.com/2014/01/black-magic-in-macro/<br>//另外猫神的很多文章都是很深入的建议有时间多去细细品味</span> |
After the macro has been written, then easy!
Instantiation method Implementation:
?
| 1 2 3 4 5 6 |
+ (BVARCSingleton *) sharedInstance { DEFINE_SHARED_INSTANCE_USING_BLOCK(^{ return [[self alloc] init]; });}<br>//Done |
Single use: The use of a single example is very simple, anywhere in the code, such as the following can be used:
to add a header file in BVAPPDELEGATE.M:
#import "NonARCSingleton.h"
#import "ARCSingleton.h"
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [NonARCSingleton sharedInstance].tempProperty = @"非ARC单例的实现"; NSLog(@"%@", [BVNonARCSingleton sharedInstance].tempProperty); [ARCSingleton sharedInstance].tempProperty = @"ARC单例的实现"; NSLog(@"%@", [ARCSingleton sharedInstance].tempProperty); return YES; } |
Additional Dry Goods
__weak,__strong