Objective c 超级allocWithZone对单例类概念有一些疑问
我是Objective-C的新手,我正在尝试创建一个基于Objective-C的单例类 在此代码中,sharedManager是一个静态方法,它将检查此类的对象是否存在。如果是,它将返回先前创建的对象,否则它将创建一个新对象 我有一些问题:Objective c 超级allocWithZone对单例类概念有一些疑问,objective-c,Objective C,我是Objective-C的新手,我正在尝试创建一个基于Objective-C的单例类 在此代码中,sharedManager是一个静态方法,它将检查此类的对象是否存在。如果是,它将返回先前创建的对象,否则它将创建一个新对象 我有一些问题: 如果sharedManager是静态的,它如何访问super 当我打印[super class]时,为什么会给出当前类名 为什么[[super allocWithZone:NULL]init]返回当前类对象 如果super在这里等于self,为什么它不调用当
sharedManager
是静态的,它如何访问super
[super class]
时,为什么会给出当前类名[[super allocWithZone:NULL]init]
返回当前类对象super
在这里等于self
,为什么它不调用当前类的allocWithZone:(NSZone*)zone
这里有两件事要考虑。首先,《可可基本面指南》有些过时。它没有考虑到苹果目前开发的一些技术,比如大中央调度和自动参考计数。allocWithZone方法中的[retain]在启用ARC的项目中无法正确编译(因为您是Obj-C的新手,我在这里假设您也是iOS/iPhone的新手,因此您应该了解这两种技术) 本线程中对不同的单例设计模式进行了很好的讨论: 然而,这是一个较老的线程,因此不考虑自动引用计数(我已经使用Louis Gerbang的答案多年了,它不再适用于支持ARC的项目) 对于启用了ARC的项目/文件(是的,ARC可以仅为单个文件启用)-我们已经转移到使用GCD并运行良好的单例:
static YourClassName * volatile sharedInstance = nil;
+ (YourClassName *)sharedInstance
{
static dispatch_once_t sharedInstanceToken;
dispatch_once(&sharedInstanceToken, ^{
sharedInstance = [[YourClassName alloc] init];
});
return sharedInstance;
}
这是怎么回事?如果您仔细看一下,您将看到dispatch_once在应用程序的整个生命周期中仅对特定对象执行一次。正如文档所说,这对于以线程安全的方式创建单例非常有用
最重要的是,我们将sharedInstance方法声明为volatile,这意味着编译器/运行时不应尝试缓存对该方法的调用,而应始终在其中执行代码。这确保了我们总是调用GCD,并且我们总是得到我们应该得到的对象
由于您是Obj-C的新手,所以我对其中的一些内容进行了润色,但一定要看看GCD、ARC,然后一旦您在Obj-C中有了坚实的基础,再看看IMP缓存,这正是volatile所阻止的 其他答案虽然指出了关于单身的好信息,但实际上并没有回答你的问题。您的问题实际上主要是基于面向对象的,您专门引用单例的事实是偶然的
self
,下面是答案的重要部分
super
在类级上下文中确实有意义,但它指的是超类本身,而不是实例
[super class]
调用当前实例上的super
方法(即self
)。如果self有一个被重写的版本,那么它将被调用,并且看起来会有所不同。由于不重写它,因此调用[self class]
与调用[super class]
是相同的
sharedGizmoManager
[Super class]
正在调用与[self class]
将调用的方法相同的实现super
是什么?在Objective-C中,+方法被恰当地称为类方法,-方法被称为实例方法。这些+方法不是真正的静态方法,因为。因此,super
和self
都是在+方法中定义的super
向MyGizmoClass的超类发送消息,但当从+方法调用时,super会查找等效的+方法,而从-method调用时,super会查找相应的-method。self
在MyGizmoClass的+方法中返回MyGizmoClass,它是一个类,而in-methodsself
是指向MyGizmoClass实例的指针
(2.)方法+class
返回self.isa
。是[super class]
调用超类的:+class
方法,但是,当self
向上传递到+方法时,它的值和类型都不会被修改(而self
的类型通过-methods向上传递时被强制转换到超类)。因此,当链上的+类方法的实现要求self.isa
时,它会得到相同的值MyGizmoClass
可以肯定的是,您可以通过从MyGizmoSuperClass派生MyGizmoClass来验证超类中的super
是否调用了+class
,您可以在其中放置覆盖:
@interface MyGizmoSuperClass : NSObject
@end
@implementation MyGizmoSuperClass
+(Class) class {
NSLog(@"yes it calls MyGizmoSuperClass:class");
return [super class];
}
@end
@interface MyGizmoClass : MyGizmoSuperClass
+(Class) classviasuper;
@end
@implementation MyGizmoClass
+(Class) classviasuper {
return [super class]; //which version of class will super call?
}
@end
int main(int argc, char *argv[])
{
NSLog(@"returned %@",[MyGizmoClass classviasuper]);
}
印刷品
是的,它调用MyGizmoSuperClass:class
返回MyGizmoClass
(3.)再次super
调用allocWithZone
的超类版本,但传递给该方法的self
值仍然指向MyGizmoClass,并且由于allocWithZone
返回接收方类的对象,因此返回MyGizmoClass
(4.)您可以轻松验证super
与self
不同。如果实现[self allocWithZone:NULL]
您的代码将调用MyGizmoClass的allocWithZone
实现并无限期循环。使用[super allocWithZone:NULL]
,将调用超类的版本。 @interface MyGizmoSuperClass : NSObject
@end
@implementation MyGizmoSuperClass
+(Class) class {
NSLog(@"yes it calls MyGizmoSuperClass:class");
return [super class];
}
@end
@interface MyGizmoClass : MyGizmoSuperClass
+(Class) classviasuper;
@end
@implementation MyGizmoClass
+(Class) classviasuper {
return [super class]; //which version of class will super call?
}
@end
int main(int argc, char *argv[])
{
NSLog(@"returned %@",[MyGizmoClass classviasuper]);
}