单例模式的作用:可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源。

  单例模式的使用场合:在这个应用程序中,共享一份资源(这份资源只需要创建初始化1次)。
一、单例模式-ARC

  1、在.m中保留一个全局的static的实例(static防止其他类extern引用 修改值)

  static id_instance;

  2、重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)

  + (id)allocWithZone:(struct _NSZone *)zone {

   if (_instance == nil) { // 防止频繁加锁

   @synchronized(self) {

              if (_instance == nil) { // 防止创建多次

   _instance = [super allocWithZone:zone];

     }

   }

  }

    return _instance;

  }

  3、提供1个类方法让外界访问唯一的实例

+ (instancetype)sharedMusicTool {

if (_instance == nil) { // 防止频繁加锁

@synchronized(self) {

if (_instance == nil) { // 防止创建多次

_instance = [[self alloc] init];

}

}

}

return _instance;

}

4、实现copyWithZone:方法

- (id)copyWithZone:(struct _NSZone *)zone {

return _instance;

}

5、如果要实现饿汉式的单例,就实现load方法。(建议不使用)

//当类加载到OC运行时环境中(内存),就会调用一次(一个类只会加载1次)

+(void)load{
    _instance = [[self alloc] init];
}

音乐单例工具类型字代码:

MusicTool.h

#import<UIKit/UIKit.h>

@interface MusicTool:UIView

//提供1个类方法让外界访问唯一的实例

+(instancetype)shareMusicTool;

@end

MusicTool.m

//单例模式:懒汉式

@implementation MusicTool

static id _instance;//static防止其他类extern引用 修改值

/**

* 如果要实现饿汉式的单例,就实现load方法

*  当类加载到OC运行时环境中(内存),就会调用一次(一个类只会加载1次)

*/

//+(void)load{

//    _instance = [[self alloc] init];

//}

   //当第一次使用这个类的时候才会调用

    //+(void)initialize{

//    NSLog(@"===initialize===");

//}

/** alloc 方法内部调用这个方法*/

 + (id)allocWithZone:(struct _NSZone *)zone {

   if (_instance == nil) { // 防止频繁加锁

   @synchronized(self) {

              if (_instance == nil) { // 防止创建多次

   _instance = [super allocWithZone:zone];

     }

   }

  }

    return _instance;

  }

/**

实例化类

*/

+ (instancetype)sharedMusicTool {

if (_instance == nil) { // 防止频繁加锁

@synchronized(self) {

if (_instance == nil) { // 防止创建多次

_instance = [[self alloc] init];

}

}

}

return _instance;

}

/**

实例化类

*/

+ (instancetype)sharedMusicTool {

if (_instance == nil) { // 防止频繁加锁

@synchronized(self) {

if (_instance == nil) { // 防止创建多次

_instance = [[self alloc] init];

}

}

}

return _instance;

}

  二:单例模式 – 非ARC

非ARC中(MRC),单例模式的实现(比ARC多了几个步骤)

实现内存管理方法

- (id)retain { return self; }

- (NSUInteger)retainCount { return 1; }

- (oneway void)release {}

- (id)autorelease { return self; }

MusicTool.m

@implementation MusicTool

static id _instance;  //static 防止其它类extern引用 修改值

+(id)allocWithZone:(struct _NSZone *)zone{}

+(instancetype)sharedMusicTool{}

-(id)copyWithZone:(NSZone *)zone{}同上

//重写release方法,不释放

  -(oneway void)release{

  }

   //重写retain方法,返回单例类

  -(instancetype)retain{

      return self; //return _instance;

   }

  //计算永远为1

  -(NSUInteger)retainCount{

      return 1;

   }

测试:

MusicTool *mt1 = [[MusicTool alloc] init];

MusicTool *mt2 = [MusicTool sharedMusicTool];

MusicTool *mt3 = [mt2 copy];

[mt2 release];//非arc环境下release

地址完全一样!

三:单例模式在ARC\MRC环境下的写法有所不同,可以用宏判断是否为ARC环境

#if __has_feature(objc_arc)

// ARC

#else

// MRC

#endif

把单例定义成宏,抽出公共类

1、HMSingleton.h

// .h文件

#define HMSingletonH(name) + (instancetype)shared##name;

// .m文件

#if __has_feature(objc_arc)

#define HMSingletonM(name) \

static id _instace; \

\

+ (id)allocWithZone:(struct _NSZone *)zone \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instace = [super allocWithZone:zone]; \

}); \

return _instace; \

} \

\

+ (instancetype)shared##name \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instace = [[self alloc] init]; \

}); \

return _instace; \

} \

\

- (id)copyWithZone:(NSZone *)zone \

{ \

return _instace; \

}

#else

#define HMSingletonM(name) \

static id _instace; \

\

+ (id)allocWithZone:(struct _NSZone *)zone \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instace = [super allocWithZone:zone]; \

}); \

return _instace; \

} \

\

+ (instancetype)shared##name \

{ \

static dispatch_once_t onceToken; \

dispatch_once(&onceToken, ^{ \

_instace = [[self alloc] init]; \

}); \

return _instace; \

} \

\

- (id)copyWithZone:(NSZone *)zone \

{ \

return _instace; \

} \

\

- (oneway void)release { } \

- (id)retain { return self; } \

- (NSUInteger)retainCount { return 1;} \

- (id)autorelease { return self;}

#endif

2、要想再整个项目中都能使用这个宏,则要在预编译pch文件中import导入这个头文件

#ifdef __OBJC__

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>

#import "HMSingleton.h"

#endif

3、使用HMSingleton工具类,实现HMMusicTool单例

HMMusicTool.h

#import <Foundation/Foundation.h>

@interface HMMusicTool : NSObject

//宏定义的方法

HMSingletonH(MusicTool)

@end

HMMusicTool.m

#import "HMMusicTool.h"

@implementation HMMusicTool

//宏定义的方法

HMSingletonM(MusicTool)

@end

4.测试:

HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];

HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];

HMMusicTool *tool3 =[[HMMusicTool alloc]init];

HMMusicTool *tool4 =[tool3 copy];

地址相同!

iOS开发实践之多线程(单例模式)的更多相关文章

  1. iOS开发网络篇—多线程断点下载

    iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...

  2. iOS 开发实践之 Auto Layout

    原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...

  3. iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)

    单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...

  4. iOS开发进阶--1.多线程简介

    学习是由已知的知识模型推理未知的知识模型的的过程. 本文适合学习完objective-c基础,想进一步提高做iOS开发的同学阅读. 在说线程的时候,我们先看看进程. 1.进程 每一个运行在系统中的应用 ...

  5. iOS开发实践-OOM治理

    概览 说起iOS的OOM问题大家第一想到的应该更多的是内存泄漏(Memory Leak),因为无论是从早期的MRC还是2011年Apple推出的ARC内存泄漏问题一直是iOS开发者比较重视的问题,比如 ...

  6. ios开发:GCD多线程

    ios有三种多线程编程技术,分别是NSThread,Cocoa NSOperation和GCD,GCD全称Grand Central Dispatch 是Apple开发的一个多核编程的解决方法,在iO ...

  7. iOS开发进阶-实现多线程的3种方法

    相关文章链接: 1.多线程简介 2.实现多线程的3种方法 ......待续 前言 在多线程简介中,我已经说明过了,为了提高界面的流畅度以及用户体验.我们务必要把耗时的操作放到别的线程中去执行,千万不要 ...

  8. 【IOS开发】《多线程编程指南》笔记

    线程是单个应用中可以并发执行多个代码路径的多种技术之一.虽然更新的技术如操作对象(Operation)和Grand Central Dispatch(GCD),提供一个等价现代化和高效的基础设施来实现 ...

  9. iOS开发笔记2:单例模式(singleton)

    每一个app有且仅有一个UIApplication,类似UIApplication“ [UIApplication sharedApplication]”这种一个类有且仅有唯一实例的设计即单例模式. ...

随机推荐

  1. thinkphp3.2.3 无法调用带下划线的模型

    thinkphp 3.2.3 如果表名中带有下划线,在分割的时候命名模型类,首字母大写,例如:order_customer_bom 为表名 .模型名为OrderCustomerBomModel 引用的 ...

  2. 吴裕雄 python 机器学习——等度量映射Isomap降维模型

    # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt from sklearn import datas ...

  3. 从零开始安装 Ambari (3) -- 安装 Ambari

    1. 安装 yum -y install ambari-server 2. ambari server 需要一个数据库存储元数据,默认使用的 Postgres 数据库.默认的用户名和密码是: amba ...

  4. Java基础之Java编译运行过程

    Java编译运行过程 程序员所编写的是以.java为后缀的文件,此文件操作系统不能正确识别,因此,首先要经过编译,生成所谓的字节码文件(.class),而字节码文件需要JVM来提供运行环境的支持. J ...

  5. Shell-2-命令之乐

    1.cat (1)基本用法 [root@cai tmp]# cat 1.txt 2.txt this is a test1 this is a test 2 (2)cat -s file(删除额外空白 ...

  6. Python学习过程(一)

    Hi,最近得知了有这么一种计算机语言,名字叫Python,下面对自己从零开始学习的一个记录.被大家所熟知的语言有很多种,比如说C语言 .java .C++  .C#等,以及javascri和火的一塌糊 ...

  7. php http 缓存(客户端缓存)

    <?php /* * Expires:过期时间 * Cache-Control: 响应头信息 * (max-age:[秒]缓存过期时间(请求时间开始到过期时间的秒数), * s-maxage:[ ...

  8. CF671A Recycling Bottles 计算几何

    It was recycling day in Kekoland. To celebrate it Adil and Bera went to Central Perk where they can ...

  9. CF708A Letters Cyclic Shift 模拟

    You are given a non-empty string s consisting of lowercase English letters. You have to pick exactly ...

  10. kuangbin专题七 HDU1540 Tunnel Warfare (前缀后缀线段树)

    During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast a ...