zoukankan      html  css  js  c++  java
  • MRC下单例模式的内存问题与ARC实现

    单例模式保证一个类只能拥有一个静态的实例,类负责创建与维护这个实例,并提供一个统一的静态(类方法)访问方式,并封锁了这个类外部的代码对这个类对象的创建。

    .h文件:

    1 #import <Foundation/Foundation.h>
    2 
    3 @interface Singleton : NSObject
    4 @property (nonatomic, copy) NSString *name;
    5 + (Singleton *) sharedInstance;
    6 @end

    这里定义了一个类方法来获取单例对象的实例。

    .m文件则比较复杂,首先要负责这个对象的创建:

     1 #import "Singleton.h"
     2 
     3 @implementation Singleton
     4 
     5 static Singleton *_sharedInstance = nil;
     6 + (Singleton *) sharedInstance {
     7     if (_sharedInstance == nil) {
     8         _sharedInstance = [[super allocWithZone:nil] init];
     9     }
    10     return _sharedInstance;
    11 }
    12 
    13 +(id)allocWithZone:(struct _NSZone *)zone {
    14     return [[self sharedInstance] retain];
    15 }

    这里令人费解的是红字部分,为什么不直接alloc一个Singletone呢?

    其实allocWithZone:nil就等价于alloc,只是这里alloc的是父类NSObject,这样做目的是把子类Singleton的allocWithZone拆解出去,拆解出来是为了复写。

    之所以要复写,是为了堵住内存分配的漏洞,因为除了+sharedInstance方法之外,用户还可能在外部程序当中alloc一个Singleton对象,而OC语言并不支持java/C#当中的将构造函数私有化。

    所以,子类复写allocWithZone的目的就显而易见、无需多言了。

    到这里还没有结束,还需要堵住其他内存管理的漏洞,一是保证直接alloc的结果和使用sharedInstance方法的效果一样,二是令release无效:

     1 -(id)copyWithZone:(NSZone *)zone {
     2     return self;
     3 }
     4 
     5 -(id)init {
     6     if (_sharedInstance) {
     7         return _sharedInstance;
     8     }
     9     self = [super init];
    10     return self;
    11 }
    12 
    13 - (id)retain {
    14     return self;
    15 }
    16 
    17 -(void)release {
    18     // Do nothing
    19 }
    20 
    21 -(id)autorelease {
    22     return self;
    23 }
    24 
    25 -(NSUInteger)retainCount {
    26     return NSUIntegerMax;
    27 }

    这样就形成了一个中规中矩的、满足内存管理的单例模式,代码显得十分啰嗦,本质原因在于OC对private支持的不好,导致我们做了很多额外工作。

    上面的代码不是线程安全的,如果需要保证单例对象的线程安全性,则需要写同步锁代码。

    ARC下的单例相对简单:

    1 + (id)sharedInstance
    2 {
    3   static dispatch_once_t pred = 0;
    4   __strong static id _sharedObject = nil;
    5   dispatch_once(&pred, ^{
    6     _sharedObject = [[self alloc] init]; // or some other init method
    7   });
    8   return _sharedObject;
    9 }

    更有甚者搞了一个宏:http://lukeredpath.co.uk/blog/2011/07/01/a-note-on-objective-c-singletons/

  • 相关阅读:
    Sokect简单入门(1)TCP协议一
    Tomcat内存溢出 解决方法
    服务器配置 ssl 证书,Nginx配置
    优秀的博客文章记录
    SpringBoot实现优雅的关机
    关于 redis 的 数据类型 和 内存模型
    微信, qq 支付宝 等相关开发 资源 记录
    设计模式 之 单列设计模式
    Swagger
    MQ服务器奔溃解决过程
  • 原文地址:https://www.cnblogs.com/Steak/p/3537798.html
Copyright © 2011-2022 走看看