iOS学习之单例

单例模式的作用:可以保证在程序运行过程中,一个类只有一个实例,而且该实例易于外界访问(说白了就是节省一些内存),其实面试的时候也就是让你手动写下单例,基本固定用GCD,没什么技术含量,平时放在一个类里面或者快捷方式里面就好了

.h文件

#import <Foundation/Foundation.h>

@interface SLDemo : NSObject<NSCopying>

+ (instancetype)sharedInstance;

@end

.m文件

id _testStr = @"testStr";
static id _instance; //static修饰一个全局变量,表示该变量只能本文件内部访问,外部无法访问 修改,用来保存唯一的单例对象

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone]; //申请内存
    });
//    if (_instance == nil) { //防止频繁加锁
//        @synchronized(self) {
//            if (_instance == nil) { //防止多次创建
//                _instance = [super allocWithZone:zone];
//            }
//        }
//    }
    return _instance;
}

+ (instancetype)sharedInstance {
    NSLog(@"%@",_testStr);
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init]; //调用allocWithZone
    });
//    if (_instance == nil) { //防止频繁加锁
//        //防止多线程一起进来,加锁
//        @synchronized(self) {
//            if (_instance == nil) { //防止多次创建
//                _instance = [[self alloc] init];
//            }
//        }
//    }
    return _instance;
}

- (id)copyWithZone:(NSZone *)zone {

    return _instance;
}

@end

调用

- (void)viewDidLoad {
    [super viewDidLoad];

    [self createSLDemo];
    
}

- (void)createSLDemo {
    
    //extern关键字是告诉编译器整个工程搜索id _testStr的全局变量,我们就可以更改搜索到后
    extern id _testStr;
    _testStr = @"string";

    SLDemo * SL1 = [SLDemo sharedInstance];
    SLDemo * SL2 = [SLDemo sharedInstance];
    SLDemo * SL3 = [SLDemo sharedInstance];
    SLDemo * SL4 = [SLDemo sharedInstance];
    
    NSLog(@"%@ %@ %@ %@",SL1, SL2, SL3, SL4);
    
}

@en

会发现打印出的地址是一样的四个,证明只调用了一次,创建了一个共同的实例

解释:上面.m文件用的是static修饰,假如去掉static,就像extern一样,拿出来可以改变,这样单例就很危险了,很可能会被其他人修改,那这样就不叫单例了

上面的单例还可以写在一个文件里,用宏调用,比如:

//.h文件宏
#define SLDemoH(name) + (instancetype)shared##name;

//.m文件宏
#define SLDemoM \
id _testStr = @"testStr"; \
static id _instance; \ 
\
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{\
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [super allocWithZone:zone];  \//申请内存
    }); \
    //    if (_instance == nil) { //防止频繁加锁
    //        @synchronized(self) {
    //            if (_instance == nil) { //防止多次创建
    //                _instance = [super allocWithZone:zone];
    //            }
    //        }
    //    }
    return _instance;
}

+ (instancetype)shared##name {
    NSLog(@"%@",_testStr);
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init]; //调用allocWithZone
    });
    //    if (_instance == nil) { //防止频繁加锁
    //        //防止多线程一起进来,加锁
    //        @synchronized(self) {
    //            if (_instance == nil) { //防止多次创建
    //                _instance = [[self alloc] init];
    //            }
    //        }
    //    }
    return _instance;
}

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

再就是可以用条件编译区分ARC 和 MRC


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值