zoukankan      html  css  js  c++  java
  • iOS-单例设计模式

    单例应用场合

    在iOS的生命周期内,有时候我们只需要某个类的一个实例。

    例如UIApplication, UIAccelerometer, NSUserDefaults, NSNotificationCenter, NSFileManger, NSBundle这些都是单例类的典型代表。

    如何创建单例类

    1. 创建一个静态对象
    2. 提供一个静态方法
    3. 重写alloc方法

    代码演示

    我们首先创建一个类Singleton, 继承自NSObject.

    添加一个静态全局变量:

    static Singleton *_singleton = nil;
    

     创建一个静态的方法:

    +(Singleton *)shareSingleton
    {
        //返回对象前需要判断,这个对象之前是否创建过,如果没有创建过,就需要创建一个对象,如果创建过,就把上一次的对象返回出去。这样可以保证创建的对象是唯一的对象
        //@synchronized:多个线程同时访问单例类,就会创建多个单例类,我们需要加锁。
        @synchronized(self)
        {
            if (_singleton == nil)
            {
                _singleton = [[self alloc]init];
            }
            return _singleton;
        }
    }
    

     我们创建单例类的目的是在全局只能创建一个对象,但是如果我们使用上面的方法创建有一个问题,就是如果用户不使用shareSingleton创建对象,而是使用alloc方法创建对象,就会又生成一个对象实例,这跟我们项目中只生成一个冲突,那么我们怎么办呢?

    第一反应,我们需要重写alloc方法,实际上我们没有必要重写alloc方法。(下文会详述)

    我们先重写alloc方法:

    +(id)alloc
    {
         @synchronized(self)
        {
            if (_singleton == nil)
            {
                _singleton = [super alloc];
            }
            return _singleton;
        }
    }
    

     既然用户可能用alloc方法创建对象,那么用户有没有可能使用allocWithZone创建对象呢?

    我们在此又需要重写allocWithZone这个方法:

    +(id)allocWithZone:(struct _NSZone *)zone
    {
        @synchronized(self)
        {
            if (_singleton == nil)
            {
                _singleton = [super allocWithZone:zone];
            }
            return _singleton;
        }
    }
    

     重写alloc,和重写allocWithZone有什么区别呢?

    allocWithZone是一个比较全面的方法,在alloc方法内部,会调用allocWithZone这个方法。

    使用allocWithZone不会调用alloc

    所以没必要重写alloc,直接重写allocWithZone即可。

     基本的代码是:

    #import "Singleton.h"
    static Singleton *_singleton = nil;
    @implementation Singleton
    +(Singleton *)shareSingleton
    {
       
        @synchronized(self)
        {
            if (_singleton == nil)
            {
                _singleton = [[self alloc]init];
            }
            return _singleton;
        }
    }
    +(id)allocWithZone:(struct _NSZone *)zone
    {
        @synchronized(self)
        {
            if (_singleton == nil)
            {
                _singleton = [super allocWithZone:zone];
            }
            return _singleton;
        }
    }
    

     上述的代码只是在ARC中可以正确使用,如果实在MRC中,有retain,copy,release, autorelease,这些方法都会使得引用计数变化,我们都需要对这些方法重写。

    -(id)retain
    {
        return _singleton;
    }
    -(void)release
    {
        
    }
    -(id)autorelease
    {
        return _singleton;
    }
    -(id)copy
    {
        return _singleton;
    }
    -(NSUInteger)retainCount
    {
        return 1;
    }
    
  • 相关阅读:
    C#发送邮件的实现实例解析
    抄录一下别人的经验
    centos学习一
    关于百度地图API批量转换成坐标的方法
    js和PHP等脚本语言for循环和if语句里面定义变量的作用域
    关于js中去取数组中的重复字符串
    关于handler返回的数据处理
    通过定义任务委托的方法处理 action
    关于点击按钮图片左右切换的随笔
    关于网站内容分享到新浪微博等的代码
  • 原文地址:https://www.cnblogs.com/wangyaoguo/p/4844607.html
Copyright © 2011-2022 走看看