美文网首页
ios单例的创建的注意事项

ios单例的创建的注意事项

作者: guoguojianshu | 来源:发表于2021-06-10 15:13 被阅读0次

单例是一个类有且只有一个实例,并且自行实例化向整个系统提供

static XSSingletonManager * instance = nil;
@implementation XSSingletonManager
+(instancetype)XSShareInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
    });
    return instance;
}
  • 做如下测试:
  XSSingletonManager * objc1 = [XSSingletonManager XSShareInstance];
    NSLog(@"%@",objc1);
    
    XSSingletonManager * objc2 = [XSSingletonManager new];
    NSLog(@"%@",objc2);

    XSSingletonManager * objc3 = [[XSSingletonManager alloc]init];
    NSLog(@"%@",objc3);

测试结果打印出来

2021-06-10 11:54:25.420181+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4730>
2021-06-10 11:54:25.420274+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4720>
2021-06-10 11:54:25.420356+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4710>

很明显,通过三种方式创建出来的三个实例是不同的,这个就违背单例的原则(有且仅有一个实例)
为了防止别人使用alloc/init的方式创建对象,我们要保证自己的类不管用什么方式创建,只能创建同一个实例对象,需要重写一个方法

+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

再次调用上面的测试代码,结果如下

2021-06-10 12:52:43.563003+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>
2021-06-10 12:52:43.563049+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>
2021-06-10 12:52:43.563085+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>

再次给单例类里面加几个属性

@property (nonatomic,strong) NSObject * object;
@property (nonatomic,strong) NSMutableArray * array;
@property (nonatomic,assign) NSInteger num;

而一些对象类的初始化,或者是基础类型的默认值设置,都是在init方法里面

-(instancetype)init{
    self = [super init];
    if (self) {
        _num = 10;
        _object = [[NSObject alloc]init];
        _array = [NSMutableArray array];
    }
    return self;
}

重写了description方法

-(NSString *)description{
    NSString * result = @"";
    result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
    result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
    result = [result stringByAppendingFormat:@" array = %p",self.array];
    result = [result stringByAppendingFormat:@" object = %p",self.object];

    return result;
}

调用上面的测试代码

2021-06-10 13:55:46.330450+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817da4c0 object = 0x281bbc5d0
2021-06-10 13:55:46.330543+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817da370 object = 0x281bbc5c0
2021-06-10 13:55:46.330615+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817dac10 object = 0x281bbc5e0

可以看到尽管使用的是同一个实例,可是他的property的值确不一样,因为尽管没有为实例重新分配内存空间,但是又因为执行了init方法,会导致property被重新初始化

所以我们需要修改单例的实现。

第1种方法

将property的初始化或者默认值设置到dispatch_once的block内部

+(instancetype)XSShareInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
        instance.num = 10;
        instance.object = [[NSObject alloc]init];
        instance.array = [NSMutableArray array];
    });
    return instance;
}


-(NSString *)description{
    NSString * result = @"";
    result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
    result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
    result = [result stringByAppendingFormat:@" array = %p",self.array];
    result = [result stringByAppendingFormat:@" object = %p",self.object];

    return result;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

测试下看下结果

2021-06-10 15:06:08.246233+0800 runLoop[5790:2237632] 此设备未越狱
2021-06-10 15:06:08.246398+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620
2021-06-10 15:06:08.246467+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620
2021-06-10 15:06:08.246533+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620

第2种

+(instancetype)XSShareInstance{
    return [[self alloc] init];
}

-(instancetype)init{
    if (self = [super init]) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [super init];
            instance.num = 10;
            instance.object = [[NSObject alloc]init];
            instance.array = [NSMutableArray array];
        });
        return instance;
    }
    return self;
}
-(NSString *)description{
    NSString * result = @"";
    result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
    result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
    result = [result stringByAppendingFormat:@" array = %p",self.array];
    result = [result stringByAppendingFormat:@" object = %p",self.object];

    return result;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

测试下看下结果:

2021-06-10 15:11:30.544370+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940
2021-06-10 15:11:30.544449+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940
2021-06-10 15:11:30.544504+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940

相关文章

  • ios单例的创建的注意事项

    单例是一个类有且只有一个实例,并且自行实例化向整个系统提供 做如下测试: 测试结果打印出来 很明显,通过三种方式创...

  • iOS 创建单例的方法

    iOS 创建单例的方法 方法一: 方法二:

  • iOS 单例的创建

    Objective-C创建单例 Swift创建单例 确保唯一性 复写allocWithZone、copyWithZ...

  • iOS单例的创建

    1、保证的程序运行过程,一个类只有一个示例,而且该实例易于供外界访问2、在iOS中有很多单例对象,比如UIAppl...

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • ios -- 创建单例

    + (JYueMyTaskManagerService*)sharedMyTaskService { static...

  • ios创建单例

    最近公司项目其中的一个控制器需要做成单例,以保证收到推送或应用内消息时弹出的是同一个界面,看了下相关资料和视频,现...

  • iOS单例创建

    常规的创建单例 .h文件中 .m文件 使用GCD写 .h中 .m文件中

  • iOS单例创建

  • iOS创建单例

    在开发过程中经常会遇到需要单例的时候,然后很多时候大家写的单例其实并不符合要求。下面介绍一个标准的单例。 一般来说...

网友评论

      本文标题:ios单例的创建的注意事项

      本文链接:https://www.haomeiwen.com/subject/bdpueltx.html