我正在尝试创建一个单例类。在搜索相关文档时,我遇到了Apple Document,它严格执行单例。我在哪里找到了以下代码:
+ (MyGizmoClass*)sharedManager
{
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
return sharedGizmoManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedManager] retain];
}
任何人都可以告诉我,为什么有必要拨打+allocWithZone:
?为什么调用+alloc
会导致崩溃?
我们也覆盖了+allocWithZone:
。为什么这样?为什么我们不能覆盖+alloc
?
提前致谢。
答案 0 :(得分:2)
您引用的文档非常陈旧。打开它时会发出警告:
退休文件
重要提示:本文档可能并不代表当前开发的最佳做法。下载和其他资源的链接可能不再有效。
恕我直言,现在这种单身人士的实施是最好的选择:https://github.com/NYTimes/objective-c-style-guide#singletons
答案 1 :(得分:0)
当一个对象创建另一个对象时,有时候做一个好主意 确定它们都是从同一个记忆区域分配的。区域 方法(在NSObject协议中声明)可用于此 目的;它返回接收者所在的区域。
正如 BBum 所说:
但实际情况是,几乎没有任何东西使用区域。它是 原本打算给予共同定位所有人的能力 与区域中的文档相关的对象,然后通过批量销毁它们 只需解除分配区域。在实践中,这被证明是行不通的 在OpenStep API中,十多年来一直没有使用这些区域。
同样在NSObject的Apple文档中:
此方法存在历史原因;内存区域不再存在 由Objective-C使用。
截至目前,我们使用这些来使用alloc
创建单例类。
@interface SomeManager : NSObject
+ (MyObject *)singleton;
@end
@implementation SomeManager
+ (MyObject *)singleton {
static id singleton = nil;
@synchronized([MyObject class]){
if (singleton == nil) {
singleton = [[self alloc] init];
}
}
return singleton;
}
@end
答案 2 :(得分:0)
作为严格的单例,可以从不调用类的init
和new
,否则将发生编译时错误。我使用NS_UNAVAILABLE
来完全隐藏init
和new
。
NS_ASSUME_NONNULL_BEGIN
@interface My: NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
+ (instancetype)shared;
@property(nonatomic, assign) NSInteger i;
@end
NS_ASSUME_NONNULL_END
和实施文件:
@implementation My
- (instancetype)initPrivate {
self = [super init];
if (self) {
// Do initialization
}
return self;
}
+ (instancetype)shared {
static id _i = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_i = [[My alloc] initPrivate];
});
return _i;
}
@end
这时,init
和new
将触发编译时错误
My *m = My.new; // Error
My *m1 = [[My alloc] init]; // Error
My.shared.i = 6; // OK
答案 3 :(得分:-1)
似乎doc有点过时了。 目前的常见做法是使用GDC
+ (MyGizmoClass *)sharedInstance {
static MyGizmoClass *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[MyGizmoClass alloc] init];
});
return instance;
}