Chỉnh sửa: Việc triển khai này đã lỗi thời với ARC. Xin vui lòng xem Làm thế nào để tôi triển khai một singleton Objective-C tương thích với ARC? để thực hiện đúng.
Tất cả các triển khai khởi tạo Tôi đã đọc trong các câu trả lời khác đều có chung một lỗi.
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
Tài liệu của Apple khuyên bạn nên kiểm tra loại lớp trong khối khởi tạo của mình. Bởi vì các lớp con gọi khởi tạo theo mặc định. Tồn tại một trường hợp không rõ ràng trong đó các lớp con có thể được tạo gián tiếp thông qua KVO. Vì nếu bạn thêm dòng sau vào một lớp khác:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C sẽ ngầm tạo một lớp con của MySingletonClass dẫn đến việc kích hoạt lần thứ hai +initialize
.
Bạn có thể nghĩ rằng bạn nên ngầm kiểm tra việc khởi tạo trùng lặp trong khối init của mình như sau:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Nhưng bạn sẽ tự bắn vào chân mình; hoặc tệ hơn là cho một nhà phát triển khác cơ hội tự bắn vào chân mình.
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR, đây là triển khai của tôi
@implementation MySingletonClass
static MySingletonClass * _instance;
+ (void) initialize {
if (self == [MySingletonClass class]){
_instance = [[MySingletonClass alloc] init];
}
}
- (id) init {
ZAssert (_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self) {
// Initialization
}
return self;
}
+ (id) getInstance {
return _instance;
}
@end
(Thay thế ZAssert bằng macro xác nhận riêng của chúng tôi; hoặc chỉ NSAssert.)