单例模式是iOS开发中常见的设计模式之一,作为一种经典的设计模式,它能够保证在整个应用程序中只会创建一个对象实例。在iOS开发中,我们常常需要在多个地方使用同一个对象,这时候通过单例模式可以方便地实现对象的共享。
苹果的框架自带的单例模式
FileManager.default
:这是一个全局的单例对象,用于提供文件管理功能UserDefaults.standard
:这是一个全局的单例对象,用于提供用户默认设置的读写功能UIApplication.shared
:这是一个全局的单例对象,用于提供应用程序级别的配置和交互功能NotificationCenter.default
:这是一个全局的单例对象,用于提供通知机制的处理和分发功能
Swift单例
Static Property + Private Initializer(推荐)
在Swift
中,使用static let
来定义单例属性是线程安全的,因为Swift
语言本身支持线程安全的延迟初始化(lazy initialization
)。即只有在第一次访问这个属性时才会创建它,且只会创建一次,保证了单例的唯一性
另外可以注意到,由于构造器使用了private
关键字,即不允许在类的外部创建实例,保证单例的原子性
class Singleton {
static let shared = Singleton(with: "param")
private init(with param: String) {}
}
个人觉得通过该方式实现单例,代码可读性强,且直观,故比较推荐
Global Variables
最直接简洁的方式:直接声明一个全局实例变量
let shared = Singleton(with: "param")
class Singleton {
init(with param: String) {}
}
在
Swift
中,全局变量使用延迟加载(lazy initialization
)的方式进行初始化。这意味着全局变量的初始化器只会在第一次访问该变量时才被调用。
Swift
的这种实现方式有一个额外的好处,就是使用了dispatch_once
函数来保证全局变量仅被初始化一次。这一点非常重要,因为仅需要初始化单例对象一次。在以前的Objective-C
中,我们通常使用@synchronized
关键字来保证线程安全并保证只有一个实例被创建。但是,Swift
中使用dispatch_once
函数可以更好地保证全局变量的唯一性和线程安全性。
OC单例
GCD是iOS中的一种多线程编程技术,也是一种常见的OC单例实现方式。以下是一个使用GCD实现的单例类示例:
@interface Singleton : NSObject
+ (instancetype)sharedInstance;
@end
@implementation Singleton
+ (instancetype)sharedInstance {
static Singleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
static Singleton *sharedInstance = nil;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (instancetype)init {
static Singleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super init];
});
return sharedInstance;
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return self;
}
@end
在上述示例中,我们使用了dispatch_once
来确保在整个应用程序生命周期中只会创建一个对象实例。同时,我们重写了allocWithZone
、init
、copyWithZone
和mutableCopyWithZone
方法,以确保在对象被复制时依然只会创建一个对象实例。
优点
- 提供了一种方便的方式来访问和共享唯一的对象实例,避免了重复创建相同的对象
- 由于单例只有一个实例,因此可以减少内存消耗和资源占用,提高应用程序的性能
- 在多线程环境下,单例可以提供一种线程安全的方式来访问和修改共享数据,避免竞态条件和死锁等问题
缺点
- 单例模式可能会导致代码耦合度较高,因为单例类被广泛使用,它的修改可能会影响整个应用程序
- 单例在应用程序中的生命周期非常长,往往从应用程序启动到关闭都存在,因此可能会导致内存泄漏、资源占用等问题
- 单例状态的混乱,一般需要对单例的状态进行监控,这样会使程序过于复杂,同时也产生很多无谓的监听
- 单例类的创建和初始化往往比较复杂,所以在设计和实现时需要考虑到其可扩展性和可维护性
总结
单例模式是iOS开发中常见的设计模式之一,它能够确保在整个应用程序中只会创建一个对象实例。在OC和Swift两种语言中,实现单例模式的方法各有不同。在OC中,我们常用懒加载和GCD来实现单例,而在Swift中,推荐使用全局常量或static变量来实现单例。无论使用哪种方法,单例模式都能够方便地实现对象的共享,提高应用程序的性能。