我已经找到了如何在目标c(非ARC)中实现单例。
// AppTools.h in my code
@interface AppTools : NSObject {
NSString *className;
}
@property ( nonatomic, retain ) NSString *className;
+ ( id ) sharedInstance;
@end // AppTools
// AppTools.m in my code
static AppTools *sharedAppToolsInstance = nil;
@implementation AppTools
@synthesize className;
- ( id ) init {
self = [ super init ];
if ( self ) {
className = [ [ NSString alloc ] initWithString: @"AppTools" ];
}
return self;
} // init
- ( void ) dealloc {
// Should never be called, but just here for clarity really.
[ className release ];
[ super dealloc ];
} // dealloc
+ ( id ) sharedInstance {
@synchronized( self ) {
if ( sharedAppToolsInstance == nil )
sharedAppToolsInstance = [ [ super allocWithZone: NULL ] init ];
}
return sharedAppToolsInstance;
} // sharedInstance
+ ( id ) allocWithZone: ( NSZone * )zone {
return [ [ self sharedInstance ] retain ];
} // allocWithZone:
- ( id ) copyWithZone: ( NSZone * )zone {
return self;
} // copyWithZone:
- ( id ) retain {
return self;
} // retain
- ( unsigned int ) retainCount {
return UINT_MAX; // denotes an object that cannot be released
} // retainCount
- ( oneway void ) release {
// never release
} // release
- ( id ) autorelease {
return self;
} // autorelease
我想知道如何在sharedInstance方法中使用allocWithZone: 在这个,allocWithZone:方法的接收器是'超级','超级'是NSObject。 虽然返回值是NSObject实例,但它被替换为sharedInstance。
className的内存空间在哪里? 我不知道如何处理这部分代码。
提前感谢。
答案 0 :(得分:3)
我认为您发布的代码太难用于创建单例。
在我的所有项目中,我使用以下代码来使用单例。它非常简单,线程安全且完美运行:
+ (CustomClass *)shared
{
static CustomClass *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[CustomClass alloc] init];
});
return singleton;
}
我相信你可以在ARC和非ARC项目中使用它。
<强>更新强>
正如评论中所提到的,它实际上是shared object
而不是singleton
,因为可以创建更多特定类的一个实例。但它足够接近。
在我看来,如果你不是在编写开源代码/库而没有其他人会使用它,那么使用共享对象并将它们视为单例可能会容易得多。
答案 1 :(得分:2)
我使用与Nekto相同的代码,但singleton = [[CustomClass alloc] init];
应为singleton = [[self alloc] init];
。
想象一下子类CustomSubclass
。如果你打电话
CustomSubclass *sharedObject = [CustomSubclass shared];
您不会获得CustomSubclass
而是CustomClass
。
答案 2 :(得分:1)
你问“那么className的记忆空间在哪里?”
大多数类本身并不实现alloc
或allocWithZone
,而是依赖于从NSObject
继承的实现。 NSObject
实现分配原始调用类的对象。
因此,在您的示例AppTools
覆盖allocWithZone
时,此实现通过调用NSObject
和{{1}来调用allocWithZone
的{{1}} }的方法执行实际分配并返回类型为super
的对象。
[注意:如果你想知道NSObject
的实现如何知道要分配什么类型的对象那么这很简单 - 调用一个继承的方法不会改变AppTools
参数到方法,NSObject
/ self
是类方法,类方法的alloc
参数引用类对象(而不是类的实例对象)本身。]