本文参考原文:iOS中的单例你用对了么? 作者:Haley_Wong
对于单例模式,总是给人一种不明觉厉的感觉。网络上有一大堆人先跟你说明了应用单例模式在开发过程中的种种好处,然后他们都用了一段差不多一样的代码来告诉你,单例模式成功完成的标准就是虽然你创建了5、6个该单例模式的对象,但是它们都指向同一块地址,说明单例模式对象只被实例化一次。
在 iOS
开发的实战我究竟要在哪些情况才用得着呢?在目前 iOS
的 arc
开发模式下,对于很多我们自定义的对象只有在我们需要的时候,才会占用到内存,一旦它们所在的控制器被销毁时,这些对象的内存就会释放内存。而如果对象使用了单例的话,那么这个对象实例化之后就将要一直占用着内存,直到程序退出,所以单例模式的对象在整个程序流程中其实是更占内存的。
知己知彼,百战不殆。要想知道使用好单例模式就需要了解单例模式的作用,单例模式虽然只实例化一次,但是为了让对象的实例让外界共享,所以它也要一直占用着内存。简单分析得到的结果就是,单例模式复用时,跳过了实例化的过程,但是却要一直占用着内存。所以我个人觉得应该使用单例模式的对象是多次实例化的结果都是一样的,或者是实例化的过程比较耗时的。比如 iOS
官方库 UIKit
中的 UIScreen
和 UIApplication
,因为这两个是跟 app
运行的设备和 app
自身信息有关,而这些东西在app过程中是不会改变的,所以实例化一次就够了,多次实例化得到了也是相同的结果。而自定义的对象中,比如用户的个人信息和 app
的检查更新结果,像这些信息多处会有用到,每次实例化都需要网络请求的,每次使用都耗费时间在网络请求上,这样会影响用户体验。所以一般像这些对象就需要使用单例模式,来减少网络请求的耗时。
我在网络上查了一大堆讲单例模式写法的文章,但是都没有讲到任何将获取到的信息加载到单例对象中的,直到看到了《iOS中的单例你用对了么? 》这篇文章才知道如何在实例化的时候添加数据。以下为我写的 demo
:
SingletonDemo.h
文件:
#import <Foundation/Foundation.h>
/**
单例模式 demo
*/
@interface SingletonDemo : NSObject
/**
应用信息词典
*/
@property (nonatomic, strong) NSDictionary *dicAppInfo;
/**
获取实例化对象方法
@return 实例化对象
*/
+ (instancetype)sharedSingeleton;
@end
SingletonDemo.m
文件:
#import "SingletonDemo.h"
// 静态全局变量,在全局共享这一份资源
static SingletonDemo *_killerApp = nil;
@implementation SingletonDemo
+ (instancetype)sharedSingeleton {
return [[self alloc] init];
}
// 重载原初始化方法
// alloc
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_killerApp = [super allocWithZone:zone];
});
return _killerApp;
}
// init
- (instancetype)init {
// GCD的一次性线程
static dispatch_once_t onceToken;
// 初始化内容
dispatch_once(&onceToken, ^{
_killerApp = [super init];
// 获取手机的应用信息
// _killerApp.dicAppInfo = [[NSBundle mainBundle] infoDictionary];
_killerApp.dicAppInfo = @{@"KillerApp":@"杀手级应用程序"};
});
return _killerApp;
}
/**
重载NSLog打印对象方法
@return 对象各个内存块的信息
*/
- (NSString *)description
{
NSString *result = @"";
result = [result stringByAppendingFormat:@"<%@: %p>\n",[self class], self];
// 词典对象的地址
result = [result stringByAppendingFormat:@" dictionary = %p\n",self.dicAppInfo];
// 词典内容
// 先转换为NSData,在转换为utf8的字符串
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.dicAppInfo options:NSJSONWritingPrettyPrinted error:&parseError];
result = [result stringByAppendingFormat:@" dictionary = %@\n", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]];
return result;
}
@end
在视图控制器上的测试:
// 单例模式test
SingletonDemo *singleton = [SingletonDemo sharedSingeleton];
NSLog(@"\n在%@控制器上的单例模式test\n%@", [self class], singleton);
运行结果:
从结果可以看出,虽然在不同的控制器上访问单例对象,但是得到的对象和对象内容的内存地址都是不变的。
第一次写简书,而且
iOS
技术目前还很菜,所以希望大家有什么好的建议希望大家可以提出来。对了,听说每为别人提供一条好的建议,出门遇到真爱的几率会提高百分之一哦!