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

时间: 2024-09-08 11:11:01

iOS学习之单例模式的相关文章

iOS学习之flappyBird游戏的实现

导言 在本人还是学生的时候,flappyBird这款游戏非常火爆,最后等到Android版的出来之后,也是很痴迷的玩了一把.可是,本人游戏天赋一直平平,几度玩得想摔手机.本文主要介绍如何开发iOS平台的flappyBird,游戏中使用了原本软件的图片资源,仅作学习交流使用.本人实现的flappyBird游戏包含游戏等级设定,排行榜,音效等功能. 技术点 flappyBird是单机游戏,主要涉及界面逻辑.图片资源.游戏动画.得分排行. 为了实现这几个功能,需要使用以下几个技术框架: 1)AVFou

iOS学习目录

IOS开发学习索引目录:http://blog.sina.com.cn/s/blog_814ecfa90102vwlu.html ---------------每走一步------------------------- ---------------就是进步------------------------- ================整理UI总结:==================== 控件的基本使用 : http://blog.sina.com.cn/s/blog_814ecfa901

IOS学习路线图

在网上搜了下,找到一IOS的学习路线图,供大家参考,我也会按照下面的思维导图来进行总结学习

ios学习笔记(二)第一个应用程序--Hello World

上一篇文章,Windows7上使用VMWare搭建iPhone开发环境介绍了在windows上安装Mac os x操作系统的方法,本篇文章将介绍Xcode的安装及第一个应用程序的开发 1.下载并安装Xcode 安装好Mac操作系统后,打开里面的浏览器就可以直接进入到Apple的官方网站,在网站里面搜索xcode就可以进入到Xcode的下载界面 在下载的过程中需要注册一个Apple ID,很简单的这里就不详细介绍了.下面的插图是我开发环境里面的搜索后的列表,供大家参考 这里需要注意下,不是所有的X

如何创建可扩展表视图中的iOS 学习和拓展优化(有待更新)

首先介绍老外的文章:<How To Create an Expandable Table View in iOS>这是老外用Swift实现 的,对应的老外github项目源码:https://github.com/appcoda/expandable-table-view 小编经过学习了老外的Expandable Table View然后用Objective-C实现了同样的效果,并且进行了很好的升级和封装. 升级和封装要点:一个xib的cell类文件管理一个xib文件,使用多态继承自共同的父类

iOS设计模式之单例模式

单例模式 基础理解 所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,默认的构造方法就会失效. 单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点. *通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象.一个最好的办法就是:让类自身负责保存它的唯一实例.这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法. 单例模式的意图是使得类的一个对象成为系统中的唯一实例. 好处 单例模式可以保证唯一的

iOS开发之单例模式

1.概述 单例模式是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源. 如果希望系统中某个类的对象只能存在一个,单例模式是最好的解决方案,iOS中最常见的单例就是UIApplication . 应用场景: 音频播放,背景音乐! 硬件资源:加速器.[UIScreen mainScreen] 一般都是通过sharedXX, mainXXX去获得这个单例对象. 常见面试题:手写单例 优点: 可以阻止其他对象实例化单例对象

iOS学习之 plist文件的读写

  在做iOS开发时,经常用到到plist文件,  那plist文件是什么呢? 它全名是:Property List,属性列表文件,它是一种用来存储串行化后的对象的文件.属性列表文件的扩展名为.plist ,因此通常被称为 plist文件.文件是xml格式的. Plist文件通常用于储存用户设置,也可以用于存储捆绑的信息 我们创建一个项目来学习plist文件的读写. 1.创建项目Plistdemo 项目创建之后可以找到项目对应的plist文件,打开如下图所示: 在编辑器中显示类似与表格的形式,可

ios学习路线

         首先恭喜你非常有眼光的学习ios开发,面对iphone6手机的全球追捧,以及苹果市值即将破万亿大关的趋势,越来越多的开发者加入了ios开发的潮流中,想在国际浪潮中分得一桶金来!     可能有好多同志对怎样学好ios有所苦恼,今天小编撸了几千行代码,着实无力继续敲下去.特意跟大家分享下学习经验.     首先是经济准备:mac电脑一台,iPhone或者ipad一部(嘿嘿!条件要求蛮高滴,让大部分程序员忘而止步,导致精通ios的人数和质量不高,物以稀为贵,ios工程师就是这个高端