http://bj007.blog.51cto.com/1701577/649413
无论是爱还是恨,你都需要单例。实际上每个iOS或Mac OS应用都至少会有UIApplication或NSApplication.
什么是单例呢?Wikipedia是如此定义的:
在软件工程中,单例是一种用于实现单例的数学概念,即将类的实例化限制成仅一个对象的设计模式。
或者我的理解是:
单例是一种类,该类只能实例化一个对象。
尽管这是单例的实际定义,但在Foundation框架中不一定是这样。比如NSFileManger和NSNotificationCenter,分别通过它们的类方法defaultManager和defaultCenter获取。尽管不是严格意义的单例,这些类方法返回一个可以在应用的所有代码中访问到的类的共享实例。在本文中我们也会采用该方法。
使用Objective-C实现单例模式的最佳方式向来有很多争论,开发者(包括Apple在内)似乎每几年就会改变他们的想法。当Apple引入了
Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0),他们也引入了一个很适合用于实现单例模式的函数。
该函数就是dispatch_once:
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上作为BOOL使用)。它还接收一个希望在应用的生命周期内仅被调度一次的代码块,对于本例就用于shared实例的实例化。
dispatch_once不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题。
如果被多个线程调用,该函数会同步等等直至代码块完成。
实际要如何使用这些呢?
好吧,假设有一个AccountManager类,你想在整个应用中访问该类的共享实例。你可以按如下代码简单实现一个类方法:
+ (AccountManager *)sharedManager {
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate; dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}
这就意味着你任何时候访问共享实例,需要做的仅是:
AccountManager *accountManager = [AccountManager sharedManager];
就这些,你现在在应用中就有一个共享的实例,该实例只会被创建一次。
该方法有很多优势:
1 线程安全
2 很好满足静态分析器要求
3 和自动引用计数(ARC)兼容
4 仅需要少量代码
-
该方法的劣势就是它仍然运行创建一个非共享的实例:
AccountManager *accountManager = [[AccountManager alloc] init];
有些时候你希望有这种行为,但如果正在想要的是仅一个实例被实例化就需要注意这点。
分享到:
相关推荐
`dispatch_once`保证一个Block只会被执行一次,通常用于初始化全局变量或单例对象。 ```swift static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 只执行一次的代码 }); ``` ### 5. GCD在实际...
在Objective-C中,创建单例通常有两种常见方法:懒汉式(Lazy Initialization)和饿汉式(Eager Initialization)。我们先来看懒汉式的实现: ```objc // 懒汉式单例 + (instancetype)sharedInstance { static ...
在ARC环境下创建单例,通常使用GCD(Grand Central Dispatch)来保证线程安全: ```objc + (instancetype)sharedInstance { static dispatch_once_t onceToken; static id sharedInstance; dispatch_once(&...
上面的懒加载初始化就是利用了`dispatch_once`。这种方式简洁且高效,能确保在任何线程中首次调用`sharedInstance`时,只执行一次初始化操作。 ```objc @interface MyClass : NSObject + (instancetype)...
在iOS开发中,创建单例通常有两种方式:GCD(Grand Central Dispatch)和懒加载。GCD利用`dispatch_once`函数确保代码只执行一次,从而保证单例的唯一性。而懒加载则是在第一次调用单例方法时才进行实例化,避免了在...
设计模式是软件工程中的一种最佳实践,用于解决在不同场景下重复出现的问题。...通过阅读提供的"iOS 设计模式——单例"相关资料,可以深入理解在iOS开发环境中如何有效利用单例模式来优化代码结构和提高程序性能。
使用GCD创建单例,利用`dispatch_once`函数保证线程安全。这种方式简单且高效,是推荐的Swift早期版本中的单例实现方式。 ```swift class Singleton { static let sharedInstance = Singleton() private ...
通过在初始化时利用dispatch_once,你创建了一个线程安全的PhotoManager单例,而且你通过使用dispatch_barrier_async和dispatch_sync的组合使得对Photos数组的读取和写入都变得线程安全了。除了上面这些,你还通过...
在这个例子中,`sharedInstance`方法利用了`dispatch_once`函数确保初始化过程只执行一次,从而确保了单例对象的唯一性。这样,无论何时通过`[MyClass sharedInstance]`调用,都会返回同一个实例。 在iOS开发中,...
单例模式是软件设计模式中的一...然而,由于`dispatch_once`在Swift 3后被弃用,现在推荐使用全局变量或内部变量的方式来创建单例。在实际开发中,应考虑代码的可读性、可维护性和性能等因素来选择合适的单例实现方法。
5. **线程安全**:为了确保在多线程环境中正确地创建和访问单例,可以在`sharedInstance`方法中添加线程同步代码,如使用GCD的`dispatch_once`或者`@synchronized`关键字。 **使用GCD实现线程安全的单例** ```objc ...
这里使用GCD的`dispatch_once`来保证线程安全,但`dispatch_once`在Swift 3之后已被废弃,所以现代Swift代码更倾向于使用静态常量`sharedInstance`来实现单例。 ### 2. `@objc` + `dispatch_once` 方式 ```swift ...
这就是如何在iOS中利用单例模式进行数据传递。这种方式的优点是减少了对象的创建和销毁开销,同时也方便了数据在多个视图间的共享。然而,需要注意的是,过度依赖单例可能导致代码紧密耦合,不易测试和维护。因此,...
在Objective-C中,我们通常通过定义一个静态方法并配合`dispatch_once`来实现单例,例如: ```objc + (instancetype)sharedManager { static id _sharedInstance = nil; static dispatch_once_t onceToken; ...
这个实现利用了GCD(Grand Central Dispatch)的`dispatch_once`函数,该函数确保其block中的代码在整个程序执行过程中只被执行一次。`sharedManager`同样是一个静态变量,`dispatch_once`保证了在多线程环境下,`[...
然而,如果我们需要在多线程环境中确保单例的安全性,可以利用GCD的队列同步特性。例如: ```swift class Singleton { static var shared: Singleton { struct SingletonWrapper { static let instance = ...
单例模式常用于管理共享资源,如网络连接、偏好设置或者数据库连接,确保这些资源在程序中的统一管理和有效利用。 单例模式的核心特点在于限制类的实例化次数,只允许创建一个对象。这样做的好处是可以避免多个对象...