IOS 单例模式

作者: 桃花流水鳜鱼肥 | 来源:发表于2016-05-13 10:38 被阅读266次

在我认为单例最大的优点就是:通过单例方式访问的实例,都是同一个。

这个优点也是我在蓝牙音乐盒项目中使用单例模式实现外设控制类和AVFoundation类的原因。
你们想,假设我在a,b,c页面都会调用到_player,那么我再a页面点击播放、上一首、下一首等等操作后,怎么让b,c页面知道并同步呢?我一开始使用的是通知。可是我试了后发现,最好的还是单例。
单例模式下的无论在那个类访问_player实例,它的状态都是最新的,也就是a点了播放,那么我在b,c页面访问_play实例,就可以知道它的状态是播放的,不需要通知。


创建单例:

.h

+ (CustomObject *)share;

.m
+ (CustomObject *)share{
    static CustomObject *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[CustomObject alloc] init];
    });
    return instance;
}

代码解释:链接
dispatch_once主要根据onceToken的值来决定是否执行block里的方法,如果onceToken==0,线程执行block里的方法,当onceToken==-1,线程不执行block。当onceToken为其他值时,线程被阻塞,等待onceToken值改变。
当线程首先调用instance,某一线程要执行block中的代码时,首先需要改变onceToken的值,再去执行block中的代码。这里onceToken的值变为了140734731430192。这样当其他线程再获取onceToken的值时,值已经变为140734731430192。其他线程被阻塞。当block线程执行完block之后。onceToken变为-1。其他线程不再阻塞,跳过block。下次再调用shareInstance时,block已经为-1。直接跳过block。这样dispatch_once在首次调用时同步阻塞线程,生成单例之后,不再阻塞线程。dispatch_once是创建单例的最优方案


通过下面代码可以理解单例的优点:

viewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    CustomObject *cv = [CustomObject share];
    cv.tempString = @"123";
}


SecondView.m

- (void)viewDidLoad {
    [super viewDidLoad];
    CustomObject *cv = [CustomObject share];
    NSLog(@"%@",cv.tempString);
}

CocoaPodsDemo[87052:9724995] 123

可以看到:
1.获取CustomObject对象的实例很方便。
2.在两个类里的实例变量实际上是同一个,没有重新alloc空间,节省了内存。当然,通过单例创建的实例常驻内存,所以资源开销就见仁见智。
3.获取实例的状态非常容易。因为是同一个实例,当我在第一个类里改变了tempString状态为@"123",我再第二个类想要获取tempString的状态马上就变成了@"123"

第三条原因让单例使用起来非常爽,也是我认为单例最大的优点,这我一开始就说过了。


注意:
访问单例类一定要通过定义的单例方法+ (CustomObject *)share。如果依旧使用alloc、init或者new就会发生下面的情况

viewController.h

- (void)viewDidLoad {
    [super viewDidLoad];
    CustomObject *cv = [CustomObject share];
    cv.tempString = @"123";
}

SecondView.h

- (void)viewDidLoad {
    [super viewDidLoad];
    CustomObject *cv = [[CustomObject alloc] init];
    NSLog(@"%@",cv.tempString);
}

CocoaPodsDemo[87052:9724995] (null)

解释:
上面两个类里获得的实例其实不是同一个,因为通过单例方式获得实例本来就是通过封锁alloc init方法实现的,但是我再SecondView重新使用了alloc/init方法实例化了。

那么如何避免呢?下面是我想的一种方法,希望指点:



- (instancetype)init{
    return [CustomObject share];
}

- (instancetype)initHidden{
    self = [super init];
    if (self) {
        
    }
    return self;
}

+ (CustomObject *)share{
    static CustomObject *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[CustomObject alloc] initHidden];
    });
    return instance;
}

相关文章

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • iOS 单例模式

    关于单例模式的详解,看完这几篇,就完全了然了。iOS 单例模式iOS中的单例模式iOS单例的写法

  • iOS 单例模式 or NSUserDefaults

    本文内容:iOS的单例模式NSUserDefaults的使用总结:iOS单例模式 and NSUserDefaul...

  • 单例模式 Singleton Pattern

    单例模式-菜鸟教程 iOS中的设计模式——单例(Singleton) iOS-单例模式写一次就够了 如何正确地写出...

  • 【设计模式】单例模式

    学习文章 iOS设计模式 - 单例 SwiftSingleton 原理图 说明 单例模式人人用过,严格的单例模式很...

  • iOS模式设计之--创建型:1、单例模式

    iOS模式设计之--1、单例模式

  • iOS单例模式容错处理

    ios 单例模式容错处理 1、单例模式的使用和问题解决 在ios开发的过程中,使用单例模式的场景非常多。系统也有很...

  • 谈一谈iOS单例模式

    这篇文章主要和大家谈一谈iOS中的单例模式,单例模式是一种常用的软件设计模式,想要深入了解iOS单例模式的朋友可以...

  • iOS知识梳理3:设计模式

    iOS有哪些常见的设计模式?单例模式/委托模式/观察者模式/MVC模式 单例模式 单例保证了应用程序的生命周期内仅...

  • 单例对象

    iOS单例模式(Singleton)单例模式的意思就是:只有一个实例;单例模式确保每个类只有一个实例,而且自行实例...

网友评论

本文标题:IOS 单例模式

本文链接:https://www.haomeiwen.com/subject/igourttx.html