Objective-C和Swift实现单例的几种方式

  在Swift开发中,我们对于跨类调用的变量常量,因为并没有OC中使用的全局头文件中写宏的形式,我们一般采用在类外定义全局变量/常量的形式来跨类调用。而问题在于目前写的项目需要在新添加的OC写的功能模块中调用Swift的全局变量,这样编译器是没办法帮你调到的。为了解决这个问题,我考虑来写一个Swift单例来保存全局变量,并由OC的类来调取数据。

  

  在iOS设计中,单例这种设计模式经常用到,也是是设计模式中最简单的一种,甚至有些模式大师都不称其为模式,称其为一种实现技巧。原因是设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,与其他对象之间并不抽象。但不可否认的是,单例已经方方面面的融入到我们的项目中来了,极为方便。

  那我们究竟在什么时候需要使用单例设计模式呢?

  顾名思义,当你只需要一个实例的时候需要使用单例,如UIApplication.sharedApplication() 等 ,就好比windows的任务管理器,回收站等等都是只能同时存在一个。

  

  一.OC中的单例设计模式有三种。简单介绍一下。

  首先,我们要创建一个继承于NSObject的类。在这个类的 .h头文件中,我们声明一个加方法。命名一般如下:

1 + (SingleInstance *)sharedInstance;

  随后在.m中实现这个方法。这里有三种形式,相对来说,安全和效率等级越来越高。

  1.直接创建

 1 static SingleInstance *singleOne;
 2
 3 + (SingleInstance *)sharedInstance {
 4
 5     if (!singleOne) {
 6
 7         singleOne = [[SingleInstance alloc] init];
 8     }
 9
10     return singleOne;
11 }

  非常好理解。创建一个静态的指针;如果指针没有指向对象,那么创一个对象并让指针持有该对象;最后返回这个指针持有的对象。因为静态,所以指针持有的对象不会被释放,也就保证了每次调取这个方法都只会返回一个对象,实现了单例的目的。

  不难看出,这种做法虽然简单明了,并且逻辑上并没有什么错误,但它并没有考虑线程安全的问题。在我们学习了多线程之后,我们就会考虑这段代码的安全性问题了。假设两条线程同时调用这段代码,并且若此时对象并未被创建,那么会创建几个对象?而若创建了多个对象,很明显与单例设计思想相违背。这样我们就有了以下的做法。

  2.加互斥锁

  根据我们刚才的分析,我们很自然会想到这样的做法:既然要防止多个线程同时访问这段代码,我们加个互斥锁,让线程们排队访问,不就解决了吗?

 1 static SingleInstance *singleTwo;
 2
 3 + (SingleInstance *)sharedInstance {
 4
 5     @synchronized (self) {
 6
 7         if (!singleTwo) {
 8
 9             singleTwo = [[SingleInstance alloc] init];
10         }
11     }
12
13     return singleTwo;
14 }

  更加简单粗暴。一言不合就上锁,这段代码只能排队执行,一个一个来。这样完美的保证了单例只有一个对象的要求。

  但是更大的问题出现了,我确实只执行了一次,但是在第二次使用这个方法的时候,if判断语句还是需要走啊?大家创建完对象仍然一点一点排队走,太影响效率了吧?

  所以,强迫症如我们程序猿,是不允许这样耗费线程资源还执行效率低下的事情发生的。更好的方法来了。

  ps:互斥锁相关再解释一下,与多线程并发有关,意义基本在于多条线程访问同一时间访问同一段代码的时候要按顺序执行,不能并发。这样能有效解决多线程的安全问题。详情请百度。

  3.使用GCD技术

 1 static SingleInstance *singleThree;
 2
 3 + (SingleInstance *)sharedInstance {
 4
 5     static dispatch_once_t onceToken;
 6
 7     dispatch_once(&onceToken, ^{
 8
 9         singleThree = [[SingleInstance alloc] init];
10     });
11
12     return singleThree;
13 }

  使用 dispatch_once 这个函数来创建对象,这样就保证了只有一个对象。问题解决。

  ps:dispatch_once是GCD中的一个对象,这个函数可以保证不管被调用几次,内部block只会执行一次,来保证代码执行的唯一性。

  

  综上,OC使用的单例方式一般就这三种,而我们使用的一般是第三种,安全性更高,执行效率更好。

  

  二.下面看看swift中的几种实现方式:

  1.

1     class SingleOne {
2
3         //单例
4         static let shareSingleOne = SingleOne()
5     }
6
7     let singleOne = SingleOne.shareSingleOne

  ps:代码编辑器中没有找到Swift语言,很尴尬..用OC凑活看吧

  一句话搞定,静态常量。所有地方用到的都是同一个。调用直接使用类名调取常量名即可。

  2.

 1     class SingleTwo {
 2
 3         //单例
 4         class func shareSingleTwo() -> SingleTwo {
 5
 6             struct Singleton{
 7
 8                 static var onceToken: dispatch_once_t = 0
 9
10                 static var single: SingleTwo?
11             }
12
13             dispatch_once(&Singleton.onceToken, {
14
15                 Singleton.single = shareSingleTwo()
16             })
17
18             return Singleton.single!
19         }
20     }
21
22     let singleTwo = SingleTwo.shareSingleTwo()

  本质上与OC第三种方法一样,都是使用dispatch_once保证其中的代码只执行一次。中间用了一个结构体来保存两个静态变量,也可以不使用这个结构体。

  3.

 1 import Foundation
 2
 3 //全局的常量
 4 let single = SingleThree()
 5
 6 class SingleThree {
 7
 8     class var sharedInstance : SingleThree {
 9
10         return single
11     }
12 }
13
14 let singleThree = SingleThree.sharedInstance

  4.

 1 import Foundation
 2
 3 class SingleFour {
 4
 5     static var sharedInstance : SingleFour {
 6
 7         struct Static {
 8
 9             static let instance: SingleFour = SingleFour()
10         }
11
12         return Static.instance
13     }
14 }
15
16 let singleFour = SingleFour.sharedInstance

  这次我们是在方法内定义静态常量。

  

  大概的创建单例的方式就是这些了。希望大家能有所收获。

时间: 2024-10-10 13:17:07

Objective-C和Swift实现单例的几种方式的相关文章

swift实现单例的四种方式

单例模式 单例模式是设计模式中最简单的一种,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象. 当你只需要一个实例的时候需要使用单例,如UIApplication.sharedApplication() 等 ,windows的任务管理器,回收站 都是只能同时存在一个. 下面看看swift中的几种实现方式: 1. import Foundation class SingleOne { //单例 static let shareSi

Swift定义单例的三种方式

第一种:使用GCD. 自定义一个class继承你要继承的类, 定义一个静态可选变量, 声明一个dispatch_once_t,并赋初始值0(0代表还没有被实例过, 如果被实例过了其值始终是1),剩下的和OC定义单例类似 1 class NetWorkTools: AFHTTPSessionManager { 2 3 //MARK: - 单例 4 static var instance: NetWorkTools? 5 static var once_t: dispatch_once_t = 0

iOS中创建单例的两种方式

刚刚开始做iOS开发的时候,不知道怎么创建单例,在网上搜的也大多数都不太全,所以总结了一下创建单例的两种方式 首先在.h文件中声明类方法 1 +(instancetype)sharedUtils; 然后在.m文件中实现它,实现的方法有两种 第一种,在创建一个对象时先判断在程序中有没有创建过这个对象 1 static PublicUtils *DefaultManager = nil; 2 3 +(instancetype)sharedUtils 4 { 5 if (!DefaultManager

java单例设计模式八种方式

单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). 比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象.SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式. 单例设计模式八种方式 单例模式有八种方式: 饿汉式( ( 静态常 量) ) 饿汉式(静态

[💯原]IOS之Objectic-C的单例的两种安全实现方案

所有转出博客园,请您注明出处:http://www.cnblogs.com/xiaobajiu/p/4122034.html Objectic-C的单例的两种安全实现方案 首先应该知道单例的实现有两大类,一个是懒汉式,一个是饿汉式.所谓的懒汉式就是在我们用到某对象(资源)的时候,去问一个负责提供的方法要那个对象.那个方法发现没有这个资源时就去创建资源,如果是已经有该资源时就直接返回这个资源.而饿汉式就是那个负责提供的方法早已为我们准备好了我们想要的资源问它,它就提供给我们那个它早就准备好了的资源

浅谈单例的三种实现--C#

传统的double check : public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (padlock) { if (i

单例的几种写作方式和序列化

2015-09-02 16:02:07 推荐一篇大神的文章,好久之前就看过这篇文章,而且本文的思路就来自这篇文章~其实有了大牛的文章,本文可写可不写,但是为了给自己总结一下,就写了~ http://callmegod.iteye.com/blog/1474441 单例的作用想必大家都知道,也一直在用,但是到底怎样的单例是“比较”完美的单例模式呢?我也不知道,但是我一直在寻找答案~ 下面我简单总结一下单例吧,否则太乱了 Part 1:单例的几种实现方式 1. 恶汉式:指在类加载或者被初始化的时候,

单例的2种使用方式

一直都对设计模式,限于书本的理论知识,今天终于用到了众多设计模式中的一种,单例模式. 一共有2种使用方法.第一种是用它里面的函数,第二种是用它里面的变量. 上代码: 第一种,用里面的函数. 单例.h @interface NetManager : NSObject + (id)sharedManager; -(void)firstPrintf; -(void)secondPrintf; -(void)threeprintf; -(void)fourprintf; @end 单例.m static

IOS单例的两种实现方式

单例模式算是开发中比较常见的一种模式了.在iOS中,单例有两种实现方式(至少我目前只发现两种). 根据线程安全的实现来区分,一种是使用@synchronized ,另一种是使用GCD的dispatch_once函数. [email protected]synchronized 实现 static InstanceClass *instance; + (InstanceClass *)defaultInstance{ @synchronized (self){ if (instance == ni