Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 超级allocWithZone对单例类概念有一些疑问_Objective C - Fatal编程技术网

Objective c 超级allocWithZone对单例类概念有一些疑问

Objective c 超级allocWithZone对单例类概念有一些疑问,objective-c,Objective C,我是Objective-C的新手,我正在尝试创建一个基于Objective-C的单例类 在此代码中,sharedManager是一个静态方法,它将检查此类的对象是否存在。如果是,它将返回先前创建的对象,否则它将创建一个新对象 我有一些问题: 如果sharedManager是静态的,它如何访问super 当我打印[super class]时,为什么会给出当前类名 为什么[[super allocWithZone:NULL]init]返回当前类对象 如果super在这里等于self,为什么它不调用当

我是Objective-C的新手,我正在尝试创建一个基于Objective-C的单例类

在此代码中,sharedManager是一个静态方法,它将检查此类的对象是否存在。如果是,它将返回先前创建的对象,否则它将创建一个新对象

我有一些问题:

  • 如果
    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不等于self,但您调用的一些方法:例如,
    [Super class]
    正在调用与
    [self class]
    将调用的方法相同的实现

  • (1.“静态函数”中的
    super
    是什么?在Objective-C中,+方法被恰当地称为类方法,-方法被称为实例方法。这些+方法不是真正的静态方法,因为。因此,
    super
    self
    都是在+方法中定义的
    super
    向MyGizmoClass的超类发送消息,但当从+方法调用时,super会查找等效的+方法,而从-method调用时,super会查找相应的-method。
    self
    在MyGizmoClass的+方法中返回MyGizmoClass,它是一个类,而in-methods
    self
    是指向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]); }