创建一个单例很多办法。我先列举一个苹果官方文档中的写法。

  1. static AccountManager *DefaultManager = nil;
  2. + (AccountManager *)defaultManager {
  3. if (!DefaultManager) DefaultManager = [[self allocWithZone:NULL] init];
  4. return DefaultManager;
  5. }

当然,在iOS4之后有了另外一种写法:

  1. + (AccountManager *)sharedManager
  2. {
  3. static AccountManager *sharedAccountManagerInstance = nil;
  4. static dispatch_once_t predicate;
  5. dispatch_once(&predicate, ^{
  6. sharedAccountManagerInstance = [[self alloc] init];
  7. });
  8. return sharedAccountManagerInstance;
  9. }

该写法来自 objcolumnist,文中提到,该写法具有以下几个特性:

1. 线程安全。

2. 满足静态分析器的要求。

3. 兼容了ARC

然后我还有点好奇的是dispatch_once,这个函数,没见过啊。

于是就到官方的文档里找找看,是怎么说的。

下面是官方文档介绍:

dispatch_once

Executes a block object once and only once for the lifetime of an application.

void dispatch_once(

dispatch_once_t *predicate,

dispatch_block_t block);

Parameters

predicate

A pointer to a dispatch_once_t structure that is used to test whether the block has completed or not.

block

The block object to execute once.

Discussion

This function is useful for initialization of global data (singletons) in an application. Always call this function before using or testing any variables that are initialized by the block.

If called simultaneously from multiple threads, this function waits synchronously until the block has completed.

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage is undefined.

Availability

  • Available in iOS 4.0 and later.

Declared In

dispatch/once.h

我们看到,该方法的作用就是执行且在整个程序的声明周期中,仅执行一次某一个block对象。简直就是为单例而生的嘛。而且,有些我们需要在程序开头初始化的动作,如果为了保证其,仅执行一次,也可以放到这个dispatch_once来执行。

然后我们看到它需要一个断言来确定这个代码块是否执行,这个断言的指针要保存起来,相对于第一种方法而言,还需要多保存一个指针。

方法简介中就说的很清楚了:对于在应用中创建一个初始化一个全局的数据对象(单例模式),这个函数很有用。

如果同时在多线程中调用它,这个函数将等待同步等待,直至该block调用结束。

这个断言的指针必须要全局化的保存,或者放在静态区内。使用存放在自动分配区域或者动态区域的断言,dispatch_once执行的结果是不可预知的。

总结:1.这个方法可以在创建单例或者某些初始化动作时使用,以保证其唯一性。2.该方法是线程安全的,所以请放心大胆的在子线程中使用。(前提是你的dispatch_once_t *predicate对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。)

转:http://blog.sina.com.cn/s/blog_69081e0601019m1z.html

iOS 创建单例的两种方法的更多相关文章

  1. IOS创建单例的两种方法

    1.0  苹果官方写法:  static AccountManager *DefaultManager = nil; + (AccountManager *)defaultManager { if ( ...

  2. 【iOS开发】创建单例的两种方法

    创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy   static AccountManager *DefaultManager = nil; + ( ...

  3. iOS单例的两种实现

    单例模式算是开发中比较常见的一种模式了.在iOS中,单例有两种实现方式(至少我目前只发现两种).根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_o ...

  4. objc单例的两种安全实现方案

    所有转出博客园,请您注明出处:http://www.cnblogs.com/xiaobajiu/p/4122034.html objc的单例的两种安全实现方案 首先应该知道单例的实现有两大类,一个是懒 ...

  5. .net中创建xml文件的两种方法

    .net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...

  6. 使用express创建node服务器的两种方法及区别

    使用express创建node服务器有两种方法,如下所示: 方法一: var express = require('express'); var app = express(); app.listen ...

  7. iOS:创建单例对象的两种方式

    单例模式:创建单例对象的两种方式 方式一:iOS4版本之前      static SingleClassManager *singleManager = nil;      +(SingleClas ...

  8. js阻止表单提交的两种方法

    下面直接看代码. <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  9. AutoCAD.NET二次开发:创建自定义菜单的两种方法比较

    目前我已经掌握的创建CAD菜单方法有两种: COM方式: http://www.cnblogs.com/bomb12138/p/3607929.html CUI方式: http://www.cnblo ...

随机推荐

  1. KnockoutJs学习笔记(七)

    if binding与visible binding类似.不同之处在于,包含visible binding的元素会在DOM中一直保存,并且该元素相应的data-bind属性会一直保持,visible ...

  2. linux convert mp3 to wav and opus to wav

    link :  https://www.cyberciti.biz/faq/convert-mp3-files-to-wav-files-in-linux/ Install mpg321 or mpg ...

  3. CentOS 7 之安装 Oracle 11gR2

    一.准备工作 1.下载Oracle安装包:linux.x64_11gR2_database_1of2.zip 和 linux.x64_11gR2_database_2of2.zip ,可以下载到本地, ...

  4. Python json使用

    转自:https://www.cnblogs.com/wangyayun/p/6699184.html?utm_source=tuicool&utm_medium=referral 使用Pyt ...

  5. LOOPS 概率dp

    题意:迷宫是一个R*C的布局,每个格子中给出停留在原地,往右走一个,往下走一格的概率,起点在(1,1),终点在(R,C),每走一格消耗两点能量,求出最后所需要的能量期望 简单概率dp 注意   原地不 ...

  6. Windows下PHP多线程扩展pthreads的安装

    pthreads扩展安装步骤 1.查看phpinfo() 获取PHP版本号及位数(x86表示32位,x64表示64位).编译器版本.PHP配置文件加载所在位置等.如下图所示: 2.pthreads扩展 ...

  7. 新手:Qt之QLabel类的应用

    在Qt中,我们不可避免的会用到QLabel类.而Qlabel的强大功能作为程序员的你有多少了解? 下面,跟着我一起在来学习一下吧! 1.添加文本 Qlabel类添加文本有两种方式,一种是直接在实现时添 ...

  8. springmvc配置MappingJackson2HttpMessageConverter实现属性驼峰和下划线的转换

    需求 php调用java接口时,因为php那边的属性都是下划线风格,java这边的属性都是驼峰的风格.配置springmvc的json转换,在requestBody的时候(调用对象的set 方法)将j ...

  9. SpringMVC(十) RequestMapping RequestHeader注解

    在控制器方法中,通过类似 RequestHeader(value="Accept-Lanaguage") String lan 可以获取请求头信息. 控制器方法: package ...

  10. Android中加载事件的方式

    Android中加载事件的方式 通过内部类的方式实现 通过外部类的方式实现 通过属性的方式实现 通过自身实现接口的方式实现 通过内部类的方式实现 Demo btn_Login.setOnClickLi ...