zoukankan      html  css  js  c++  java
  • iOS

    单例创建的第一种写法:多线程 dispatch_once

    一般写法:

    #import <Foundation/Foundation.h>
    
    
    @interface FNWaterMarkHelper : NSObject
    
    
    + (instancetype)sharedWaterMark;  
    
    @end
    #import "FNUserInfoManager.h"
    static FNWaterMarkHelper *_showWaterMark = nil;
    
    + (instancetype)sharedWaterMark{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _showWaterMark = [[self alloc] init];
        });
        
        return _showWaterMark;
    }
    
    
    @end

    输出测试:

    #import <Foundation/Foundation.h>  
    #import "Downloader.h"  
      
    int main(int argc, const char * argv[]) {  
        @autoreleasepool {  
            FNWaterMarkHelper *obj1 = [FNWaterMarkHelper sharedWaterMark];  
            NSLog(@"obj1 = %@", obj1);  
              
            FNWaterMarkHelper *obj2 = [FNWaterMarkHelper sharedWaterMark];  
            NSLog(@"obj2 = %@", obj2);  
              
            FNWaterMarkHelper *obj3 = [[FNWaterMarkHelper alloc] init];  
            NSLog(@"obj3 = %@", obj3);  
        }  
          
        return 0;  
    }  

    结果:

    obj1 = <Downloader: 0x78f25be0>  
    obj2 = <Downloader: 0x78f25be0>  
    obj3 = <Downloader: 0x79225e00>  

    解释:

    可以看到,当我们调用 sharedWaterMark 方法时获取到的对象是相同的,但是当我们通过alloc和init来构造对象的时候,得到的对象却是不一样的。

    那么问题就来了,我们通过不同的途径得到不同的对象,显然是不行的。我们必须要确保对象的唯一性,所以我们就需要封锁用户通过alloc和init以及copy来构造对象这条道路。

    创建对象分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,OC内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用 sharedWaterMark 方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用sharedDownloader方法返回单例对象。

    改进:

    #import "FNUserInfoManager.h"
    static FNWaterMarkHelper *_showWaterMark = nil;
    
    + (instancetype)sharedWaterMark{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _showWaterMark = [[super allocWithZone:NULL] init];
        });
        
        return _showWaterMark;
    }
    
    + (id)allocWithZone:(struct _NSZone *)zone {  
        return [FNWaterMarkHelper sharedWaterMark];  
    }  
      
    - (id)copyWithZone:(struct _NSZone *)zone {  
        return [FNWaterMarkHelper sharedWaterMark];  
    }  
    
    @end

    输出结果:

    obj1 = <Downloader: 0x7ca42e70>  
    obj2 = <Downloader: 0x7ca42e70>  
    obj3 = <Downloader: 0x7ca42e70>  

    搞定!

    单例创建的第二种方法构造函数,不常用:

    static PublicUtils *DefaultManager = nil;
    
    +(instancetype)sharedUtils
    {
        if (!DefaultManager)
            DefaultManager = [[self allocWithZone:NULL] init];
        
        return DefaultManager;
    }
  • 相关阅读:
    MIne FirstBlog
    P6563 [SBCOI2020]一直在你身旁
    P6563 [SBCOI2020]一直在你身旁
    T122085 [SBCOI2020]时光的流逝
    LC 918. Maximum Sum Circular Subarray
    1026 Table Tennis
    LC 1442. Count Triplets That Can Form Two Arrays of Equal XOR
    LC 1316. Distinct Echo Substrings
    LC 493. Reverse Pairs
    1029 Median (二分)
  • 原文地址:https://www.cnblogs.com/qiyiyifan/p/10965729.html
Copyright © 2011-2022 走看看