iOS 中的单例模式

在iOS中有很多单例对象,比如UIApplication,UIScreen等等,那我们自己可以实现单例吗?答案是肯定的,请往下看

ARC中的单例实现
//.h文件
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
//单例方法
+(instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"
@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
    return [[self alloc] init];
}
////alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    //只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}
//初始化方法
- (instancetype)init{
    // 只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super init];
    });
    return _instance;
}
//copy在底层 会调用copyWithZone:
- (id)copyWithZone:(NSZone *)zone{
    return  _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone{
    return  _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
    return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
    return _instance;
}
@end
  • 测试代码及运行结果
#import <Foundation/Foundation.h>
#import "Singleton.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Singleton *s1 = [[Singleton alloc]init];
        Singleton *s2 = [Singleton sharedSingleton];
        
        Singleton *s3 = [[Singleton alloc]init];
        Singleton *s4 = [Singleton sharedSingleton];
        Singleton *s5 = [s4 copy];
        NSLog(@"%p %p %p %p %p",s1,s2,s3,s4, s5);
    }
    return 0;
}
运行结果
2015-08-29 21:07:01.869 Singleton-ARC[42202:784939] 0x100114760 0x100114760 0x100114760 0x100114760 0x100114760
非ARC中的单例实现
  • 因为在非ARC中,需要我们自己管理内存,所以实现稍微负责一点
//.m文件
#import <Foundation/Foundation.h>
//单例方法
@interface Singleton : NSObject
+ (instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"

@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
    //系统的大多数类方法都有做autorelease,所以我们也需要做一下
     return [[[self alloc] init] autorelease];
}
//alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    //只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}
//初始化方法
-(instancetype)init{
    // 只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super init];
    });
    return _instance;
}
- (oneway void)release{
    //什么都不做 保证单例对象不被销毁
}
//返回本身 保证只有一个单例对象
- (instancetype)retain{
    return _instance;
} 
//计数器为1 保证只有一个单例对象
- (NSUInteger)retainCount{
    return 1;
}
//copy在底层 会调用copyWithZone:
+ (id)copyWithZone:(struct _NSZone *)zone{
    return  _instance;
}
- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
    return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
    return _instance;
}
@end
  • 因为要保证单例对象在程序运行期间一直存在,所以不需要实现release方法和dealloc方法
  • 测试代码及运行结果
#import <Foundation/Foundation.h>
#import "Singleton.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Singleton *s1 = [[Singleton alloc]init];
        Singleton *s2 = [Singleton sharedSingleton];
        
        Singleton *s3 = [[Singleton alloc]init];
        Singleton *s4 = [Singleton sharedSingleton];
        Singleton *s5 = [s4 copy];
        
        
        NSLog(@"%p %p %p %p %p",s1,s2,s3,s4, s5);
        [s1 release];
        [s3 release];
        [s5 release];
        
    }
    return 0;
}
运行结果
2015-08-29 21:01:43.770 Singleton-非ARC[42192:782473] 0x100206880 0x100206880 0x100206880 0x100206880 0x100206880
  • 也可以把上面的代码抽出一个宏,以ARC为例
//.h文件   ##表示拼接字符
#define SingletonH(methodName) +(instancetype)shared##methodName;
//.m文件
#define SingletonM(methodName)\
\
static id _instance = nil;\
+(instancetype)sharedSingleton{\
    return [[self alloc] init];\
}\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [super allocWithZone:zone];\
    });\
    return _instance;\
}\
- (instancetype)init{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [super init];\
    });\
    return _instance;\
}\
- (id)copyWithZone:(NSZone *)zone{\
    return  _instance;\
}\
+ (id)copyWithZone:(struct _NSZone *)zone{\
    return  _instance;\
}
  • 以上代码如果有上面不对的地方,敬请纠正,谢谢!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • @WilliamAlex大叔 前言 目前流行的社交APP中都离不开单例的使用,我们来举个例子哈,比如现在流行的"糗...
    Alexander阅读 1,933评论 6 28
  • 单例的概念 单例类保证了应用程序的生命周期中有且仅有一个该类的实例对象,而且易于外界访问。在iOS中有很多单例类,...
    伶俐ll阅读 394评论 0 1
  • 单例模式大概是设计模式中最简单的一个。本来没什么好说的,但是实践过程中还是有一些坑。所以本文小结一下在iOS开发中...
    qiushuitian阅读 3,441评论 1 21
  • 仰望星空,筑梦踏实 在13期创业大学开学典礼上,她一首非常好听的英文歌沸腾了全场。 来到iwill短短几个月的时间...
    小C大c阅读 288评论 0 0
  • 木地板被肥皂水洗得发白,散发淡淡的清香。蕾丝白纱窗帘的小孔透进一缕缕阳光,窗台上的几盆小多肉植物舒服地...
    谱楚的世界阅读 318评论 6 11