ios 开发----单利

2025-10-04 03:20:10

1、=====方法一  、废除  init / new  方法

//    .h文件中

@interface UserManager : NSObject

+ (UserManager *) sharedManager;    //添加类方法

//    .m文件中

第一步、废除原有 初始化方法   抛出异常

- (instancetype) init {

    @throw [NSException exceptionWithName:@"" reason:@"不能调用init/new方法初始化CDUserManager对象" userInfo:nil];

}

第二步、方法重写  方法私有化

- (instancetype) initPrivate {

    if (self = [super init]) {

       //设置属性   自定义

        User *user = [[User alloc] init];

        user.username = @"AAA";

        user.password = @"123456";

        user.email = @"admin@1000phone.com";

    }

    return self;

}

第三步、创建单例对象(唯一的)

+ (UserManager *) sharedManager{

    static UserManager *manager = nil; //静态实例  并初始化

    @synchronized (self) {   // 同步保护  只允许一个线程进入 排队等候

        if (!manager) { //如果为空 则新建 分配内存 初始化为私有

            manager = [[self alloc] initPrivate];

        }

    }

    return manager;//返回本类型 实例

}

ios 开发----单利

2、如果你用   init  或 new 来创建对象 就会抛出异常

UserManager *uuu = [UserManager new];

UserManager *uuu = [[UserManager  alloc]init];

ios 开发----单利

3、====方法二 、可以  init / new  方法

为了防止别人不小心利用alloc/init方式创建示例,也为了防止别人故意为之,我们要保证不管用什么方式创建都只能是同一个实例对象,这就得重写另一个方法,实现如下:

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

写法一、

static HLTestObject *instance = nil; 

+ (instancetype)sharedInstance{    

      static dispatch_once_t onceToken;    

      dispatch_once(&onceToken, ^{   

     // 设置属性     

      instance = [[[self class] alloc] init];        

      instance.height = 10;       

      instance.object = [[NSObject alloc] init];        

      instance.arrayM = [[NSMutableArray alloc] init];    

      });   

      return instance; 

//重写方法

+ (instancetype)allocWithZone:(struct _NSZone *)zone{    

       static dispatch_once_t onceToken;    

       dispatch_once(&onceToken, ^{        

       instance = [super allocWithZone:zone];    

       });    

       return instance; 

}

写法二、

static HLTestObject *instance = nil; 

+ (instancetype)sharedInstance{   

      return [[self alloc] init]; 

}

 - (instancetype)init{    

       static dispatch_once_t onceToken;    

      dispatch_once(&onceToken, ^{    

      instance = [super init];   //== 

      //设置属性        

      instance.height = 10;          

      instance.object = [[NSObject alloc] init];        

      instance.arrayM = [[NSMutableArray alloc] init];    

      });    

      return instance; 

}  

//重写方法

+ (instancetype)allocWithZone:(struct _NSZone *)zone{   

       static dispatch_once_t onceToken;    

       dispatch_once(&onceToken, ^{       

       instance = [super allocWithZone:zone];    

      });   

      return instance;

 }

//下面的方法  是为 copy  mutableCopy  得到的对象也是唯一的

//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; 

}

可以用如下图的三种方法创建对象,得到的都是同一个

ios 开发----单利

ios 开发----单利

4、====dispatch_once 与 @synchronized (self) 的比较

使用dispatch_once可以简化代码并且彻底保证线程安全,开发者无需担心加锁或同步。此外,dispatch_once更高效,它没有使用重量级的同步机制,若是那样做的话,每次运行代码前都要获取锁。相反,此函数采用“原子访问”来查询标记,以判断其所对应的代码原来是否已经执行过

5、把单利抽出一个宏,以ARC为例

ios 开发----单利

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢