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

  单例模式的使用场合:在这个应用程序中,共享一份资源(这份资源只需要创建初始化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. Vue2.0学习--Vue数据通信详解

    一.前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.组件间如何传递数据就显得至关重要.本文尽可能罗列出一些常见的数据传递方式,如p ...

  2. Oracle中merge into语法

    merge into 语句就是insert和update的一个封装,简单来说就是: 有则更新,无则插入 下面说怎么使用 MERGE INTO table_Name  T1(匿名) using (另外一 ...

  3. swift基础语法之——变量和常量

    swift使用let关键字来定义常量,使用var来定义变量,变量在使用前必须初始化(赋初始值) swift是类型安全语音,即不同类型的变量不能一起运算,必须转成同一类型才可以 变量的类型在声明时不必给 ...

  4. linux中断和异常睡眠问题

    中断和异常: 中断只代表异步中断,异常代表同步中断,这样系统调用是异常处理,不是中断处理. 这里异常处理是可以休眠block的,因为异常处理所需的数据是存储在异常栈中,而每个进程都有一个异常栈,所以异 ...

  5. 黑马集合学习 自定义ArrayList01

    package demo; import java.util.Arrays; public class MyArrayList<T> { Object[] t; int size; pri ...

  6. 利用zookeeper生成唯一id,通用性代码

    在上篇中是写死的,这章就写出通用的 package com.cxy.com.cxy.curator; import java.util.concurrent.ExecutorService; impo ...

  7. C++的一种业务分发方案(另类的工厂模式)

    在C++中,传统的业务分发.总要写一大串的switch-case,并且每次添加新业务时.都要在原有的switch-case里加一个分支,这就违反了设计模式中的开放封闭原则. 下面这样的方案,就全然去除 ...

  8. SprimgMVC学习笔记(一)—— SpringMVC入门

    一.什么是 SpringMVC ? 在介绍什么是 SpringMVC 之前,我们先看看 Spring 的基本架构.如下图: 我们可以看到,在 Spring 的基本架构中,红色圈起来的 Spring W ...

  9. Report Server运行后一直处于加载状态

    描述:对Report server做了一个小练习,算是入门,但发现运行起来后,页面一直处于加载状态,不知为何? 解决:查了一下网上的资料,解决的方法是 protected void Page_Load ...

  10. Java中的两个类:Desktop和SystemTray

    在JDK6中 ,AWT新增加了两个类:Desktop和SystemTray,前者可以用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端给指定的邮箱发邮件,用默认应用程序打开或编辑文件(比如 ...