iOS单例模式之MRC和ARC单例类

在iOS的开发中,我经常会用到的一种设计模式:单例模式,目的是让这个对象只实例化一次,在内存中只有一份内存。而且是常驻内存,不会被释放。

手写一个单例也许我们都已经很熟悉,但是真的写的很完善吗,有哪些需要注意的呢?

  • 全局静态实例对象
  • 提供一个供外部调用的类方法
  • 加线程锁,防止重复实例化
  • 重写内存分配方法

下面我们就在MRC和ARC两种模式下看一下单例的写法有什么区别。

MRC单例

首先我们来看一下手动管理内存时的单例是怎么写的:
头文件MRCSingleton.h

//
//  MRCSingleton.h
//  Singleton
//
//  Created by z on 2019/5/23.
//  Copyright © 2019年 com.jzsec. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MRCSingleton : NSObject <NSCopying,NSMutableCopying>

//给外部提供的类方法
+ (instancetype)shareInstance;

@end

NS_ASSUME_NONNULL_END

实现文件MRCSingleton.m

//
//  MRCSingleton.m
//  Singleton
//
//  Created by z on 2019/5/23.
//  Copyright © 2019年 com.jzsec. All rights reserved.
//

#import "MRCSingleton.h"

static MRCSingleton *_instance;

@implementation MRCSingleton

//给外部提供的类方法
+ (instancetype)shareInstance
{
    //加互斥锁解决多线程访问安全问题
//    @synchronized (self)
//    {
//        if (_instance == nil)
//        {
//            _instance = [[MRCSingleton alloc] init];
//        }
//    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[MRCSingleton alloc] init];
    });
    
    return _instance;
}

//实例化 分配内存
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //加互斥锁解决多线程访问安全问题
//    @synchronized (self)
//    {
//        if (_instance == nil)
//        {
//            _instance = [super allocWithZone:zone];
//        }
//    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    
    return _instance;
}

//实现copy协议
-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

- (id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}

- (id)copy
{
    return _instance;
}

-(id)mutableCopy
{
    return _instance;
}

//覆盖与内存相关的方法
- (instancetype)retain
{
    return _instance;
}

- (oneway void)release
{
    
}

- (NSUInteger)retainCount
{
    return UINT_MAX;
}

- (instancetype)autorelease
{
    return _instance;
}

@end
ARC单例

自动管理内存时的单例是怎么写的:
头文件ARCSingleton.h

//
//  ARCSingleton.h
//  Singleton
//
//  Created by z on 2019/5/23.
//  Copyright © 2019年 com.jzsec. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ARCSingleton : NSObject <NSCopying,NSMutableCopying>

//给外部提供的类方法
+ (instancetype)shareInstance;

@end

NS_ASSUME_NONNULL_END

实现文件ARCSingleton.m

//
//  ARCSingleton.m
//  Singleton
//
//  Created by z on 2019/5/23.
//  Copyright © 2019年 com.jzsec. All rights reserved.
//

#import "ARCSingleton.h"

static ARCSingleton *_instance;

@implementation ARCSingleton

//给外部提供的类方法
+ (instancetype)shareInstance
{
    //加互斥锁解决多线程访问安全问题
    //    @synchronized (self)
    //    {
    //        if (_instance == nil)
    //        {
    //            _instance = [[ARCSingleton alloc] init];
    //        }
    //    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[ARCSingleton alloc] init];
    });
    
    return _instance;
}

//实例化 分配内存
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //加互斥锁解决多线程访问安全问题
    //    @synchronized (self)
    //    {
    //        if (_instance == nil)
    //        {
    //            _instance = [super allocWithZone:zone];
    //        }
    //    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    
    return _instance;
}

//实现copy协议
-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

- (id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}

- (id)copy
{
    return _instance;
}

-(id)mutableCopy
{
    return _instance;
}

@end
instancetype 和 id

id我们经常使用,当做一个类型不确定的OC对象,instancetype在一些系统的API里也经常看到,也是当做一个类型不确定的OC对象,那么它和id有什么区别呢?

比如刚才我们ARC单例的类方法,新增一个返回id类型的类方法:

//给外部提供的类方法
+ (instancetype)shareInstance;

//用于区别instancetype的测试方法
+ (id)makeInstance;

//实例方法
- (void)test;

实现:

//用于区别instancetype的测试方法
+ (id)makeInstance
{
    return [[[self class] alloc] init];
}

- (void)test
{
    
}

实例化并调用,此时就会收到警告:

因为shareInstance返回的类型是instancetype,在编译期会进行类型检测,检测到它是ARCSingleton对象,所以识别到test方法;而makeInstance返回的是id类型,不检测对象类型,所以不知道它响应test方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值