• iOS学习之单例模式


      单例模式的作用是解决“应用中只有一个实例”的一类问题。

    (一)问题的提出 

      在一个iOS 应用的生命周期中,有时候我们只需要某个类的一个实例。例如,iOS 设备都有一个重力加速计硬件设备,要访问设备在x轴、y轴和z轴上的重力加速度,就必然要有一个类能够与硬件设备沟通来实时获得这些数据,这个类就是UIAccelerometer 。除了实时地获得数据,该类还能够保持x 轴、y轴和z 轴的状态。但是这个类只需要一个实例就够了,如果有多个实例,就会占用过多的内存。
    再有,当应用程序启动时,应用的状态由UIApplication 类的一个实例维护,这个实例代表了整个“应用程序对象”,它只能是一个实例,其作用是实现应用程序中一些共享资源的访问和状态的保持等。

    (二)实现原理

      单例模式一般会封装一个静态属性,并提供静态实例的创建方法,其UML类图如图1所示。

                                   

                                           图1 单例设计模式类图

    示例代码:

    //Singleton.h 
    // 
    @interface Singleton : NSObject 
    + (Singleton*)sharedManager; 
    @property (nonatomic ,strong) NSString* singletonData; 
    @end 
     
    
    //Singleton.m  
    // 
    #import "Singleton.h" 
    @implementation Singleton 
    @synthesize singletonData = _singletonData; 
    static Singleton *sharedManager = nil; 
    + (Singleton*)sharedManager 
    { 
        static dispatch_once_t once; 
        dispatch_once(&once, ^{ 
            sharedManager = [[self alloc] init]; 
        }); 
        return sharedManager; 
    } 
    @end
    

    其中static Singleton *sharedManager 为静态变量,类方法为+ (Singleton*)sharedManager。
    sharedManager 方法采用了GCD(Grand Central Dispatch)技术,这是一种基于C语言的多线程访问技术。在上述代码中,dispatch_once 函数就是由GCD提供的,它的作用是在整个应用程序生命周期中只执行一次代码块(^{…})。 dispatch_once_t 是GCD提供的结构体,使用时需要将GCD地址传给dispatch_once 函数。dispatch_once 函数能够记录该代码块是否被调用过。
      dispatch_once函数不仅意味着代码仅会被运行一次,而且还意味着此运行还是线程同步的。也就是说,当我们使用了dispatch_once函数时,就不再需要使用诸如@synchronized之类的语句。

      将以上单例实现代码,抽成宏,代码如下:

    // @interface
    #define singleton_interface(className) 
    + (className *)shared##className;
    
    
    // @implementation
    #define singleton_implementation(className) 
    static className *_instance; 
    + (id)allocWithZone:(NSZone *)zone 
    { 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            _instance = [super allocWithZone:zone]; 
        }); 
        return _instance; 
    } 
    + (className *)shared##className 
    { 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            _instance = [[self alloc] init]; 
        }); 
        return _instance; 
    }

    (三)应用案例

      在Cocoa Touch框架中,有UIApplication、UIAccelerometer 、NSUserDefaults和NSNotificationCenter等单例类。另外,NSFileManager 和NSBundle 类虽然属于Cocoa框架的内容,但也可以在Cocoa Touch框架中使用(Cocoa框架中的单例类有NSFileManager 、NSBundle 、NSWorkspace和NSApplication 等)。 

    1. UIApplication

    UIApplication 类的实例提供了应用程序的集中控制点来保持应用的状态。UIApplication 实例总是分配给应用程序委托对象(UIApplicationDelegate ),通过应用程序委托对象来响应低内存、应用启动、后台运行和应用终止等事件。在HelloWorld 案例中,AppDelegate 就是这个应用程序的委托对象,它实现了UIApplicationDelegate协议。

    UIApplication 类有很多方法和属性,下面我们重点介绍其中几个。

    • + sharedApplication 方法。创建和获得UIApplication 实例的方法。
    • idleTimerDisabled属性。设定和获得“空闲时间禁止”的状态。idleTimerDisabled属性的默认值是NO,即默认情况下系统会锁定屏幕。当idleTimerDisabled = YES 时,则不会开启“空闲时间禁止”状态,系统不会锁定屏幕。开启这项设定需要谨慎,它会使你的应用比较耗电。
    • - openURL: 方法。可以打开一些内置的iOS 应用,其中包括打开浏览器、打开Google 地图、拨打电话、发送短信和发送E-mail 等。

    打开浏览器的示例代码如下:

    NSURL *url = [NSURL URLWithString:@"http://www.cnblogs.com/chars"]; 
    [[UIApplication sharedApplication] openURL:url]; 

    打开Google 地图时,实际上是通过内置浏览器来打开,示例代码如下:

    NSString* searchQuery = @" 清华大学"; 
    searchQuery = [searchQuery stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; 
    NSString* urlString = [NSString stringWithFormat: @"http://maps.google.com/maps?q=%@", searchQuery]; 
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]]; 

    其中NSString 的stringByAddingPercentEscapesUsingEncoding方法将字符串转换为URL编码,例如 “%E6%B8%85%E5%8D%8E%E5%A4%A7%E5%AD%A6 ”是“清华大学”的 URL 编码。
    拨打电话时,苹果官方要求使用该方法调用内置拨号程序,示例代码如下:

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://10010"]];

    发送短信时,苹果官方要求使用该方法调用内置发送短信程序,示例代码如下:

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms:10010"]]; 

    发送E-mail 时,这种方式可以发送简单的不带附件的E-mail ,示例代码如下:

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://eorient@sina.com"]];
    

    2.   UIAccelerometer

      单例类UIAccelerometer 前面也讲过,它可以访问重力加速计硬件设备,实时获得设备在x 轴、y轴和z 轴方向上的重力加速度。

      + sharedAccelerometer方法是创建和获得UIAccelerometer实例的共享方法。

      与UIApplication类似,UIAccelerometer也有对应的委托对象,其委托对象为UIAccelerometerDelegate。UIAccelerometer 将实例分配给委托对象UIAccelerometerDelegate ,然后由委托对象响应重力加速计事件。

    3.   NSUserDefaults

      单例类NSUserDefaults可以很方便地读取应用设置项目。

      + standardUserDefaults方法是创建和获得NSUserDefaults实例的静态方法。

    4.   NSNotificationCenter 

      单例类NSNotificationCenter提供信息广播通知,它采用观察者模式的通知机制。

      + defaultCenter 方法是创建和获得NSNotificationCenter实例的共享方法。

    5.   NSFileManager 

      NSFileManager 提供了访问文件系统的通用操作,可以定位、创建、复制文件和文件夹。在iOS 5和Mac OS X v10.7之后,它还可以管理存储在iCloud 上的数据。

      + defaultManager 方法是创建和获得NSFileManager 实例的方法。除了该方法外,创建NSFileMa nager对象时还可以使用实例构造方法– init。这两种方法有着比较大的差别,+ defaultManager方法总是返回相同的NSFileManager 对象,但如果要使用委托(NSFileManagerDelegate)完成基于文件的操作并接收通知,应该使用– init 方法创建一个新的实例,而不是使用共享的对象。

    6.   NSBundle 

      NSBundle 提供了动态加载(或卸载)可执行代码、定位资源文件以及资源本地化、访问文件系统等功能。

      + mainBundle方法是创建和获得NSBundle 实例的共享方法。

      单例模式无疑是Cocoa框架下最重要的设计模式之一。灵活而有机地运用设计模式,意味着编程工作的高效性和产品健壮性、安全性的提高。因此,我们应该要善于使用设计模式,将自己的开发经验与代码、设计模式完美融合起来,提高软件代码质量。

  • 相关阅读:
    python之enumerate
    PyCharm Debug 调试
    兼容性测试方法
    mongo基本命令
    mongodb启动
    安装STF
    新家
    用数组实现的最大堆(C++)
    VS2013调用GLPK求解线性规划
    转:Java读取txt文件和写入txt文件
  • 原文地址:https://www.cnblogs.com/chars/p/5006959.html
Copyright © 2020-2023  润新知