• iOS self = [super init]


    self = [super init] 这个问题一直不太明白,今天研究了一下,在stackoverflow找到了下面的答案:

    http://stackoverflow.com/questions/2956943/why-should-i-call-self-super-init

    我对这些答案简单翻译总结下:

    要明白这个问题,首先要知道self 是什么东西,我们什么时候会用到self。

    self指针,不是在实例中的保存的真实指针,而是一个隐藏的函数参数。比如我们调用 [person getName]; 时,系统会翻译为

    id objc_msgSend(id theReceiver, SEL theSelector, ...)

    这种调用,其中的 theReceiver,就是我们在实例对象的方法里可以用到的self,其实它仅仅是一个隐藏的函数参数。

    看完了self是什么,在看看super是什么,这里,可以参见这篇博文,写得非常出色:

    http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective[nil]c-runtime(1)[nil]-self-and-super/

    我把重点说一下:

    调用如下代码:

        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));

    使用 clang -rewrite-objc 这个命令后,得到的中间代码有如下关键部分:

     (void *)objc_msgSend)((id)self, sel_registerName("class")
    (void *)objc_msgSendSuper)((__rw_objc_super){ (id)self, (id)class_getSuperclass(objc_getClass("Son")) }, sel_registerName("class")

    注意,用了super去调用,其实还是把self的值传递进去了,但是,多传递了一个类名,这里就是“Son”,并且使用了objc_msgSendSuper进行消息传递。

    简单地说,super和self 都是在函数调用时,隐藏传递进去的一个参数,但是,super会从父类方法列表中先进行索引,如果找到了函数实现,就不再调用子类的函数实现了。

    看过上面的解释,其实,super和self真正指向的都是已经被分配内存的对象,在 init方法中,就是alloc后,没有初始化的一段内存空间。[super init] 就是把这块内存空间先传递给父类,去父类调用父类的init方法,返回一段部分初始化好内存空间。为了方便理解,我画了一个大概的图:

    在[super init] 之后,父类的变量应该被初始化完毕,而子类的变量还没有初始化。

    在一般情况下,写不写 self = [super init] 都无关紧要,因为 [super init] 在一般情况下的返回值,都是一段已经初始化好一部分的内存。我们自己继承NSObject的类,如果没用什么特殊方法(什么叫特殊?见下面的class cluster),就不需要写这个 self =。

    但是在特殊情况下,比如分配出错,那么 [super init] 会返回空,表明错误,这时,如果不把 self 设置为nil,而是继续指向alloc后的那块内存,之后的操作就会产生问题。

    还有一种特殊情况,叫做Class Cluster,翻译中文的话,类族,官方文档 https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/ClassClusters/ClassClusters.html

    再看一篇好的博文:

    http://blog.sunnyxx.com/2014/12/18/class-cluster/

    按照博客里的方法,我也实验了一下,截图如下:

    obj1 , obj3  不但类型不同,而且地址也不同!我如果继承了NSArray(会这样操作吗?没有实验),并且重写了init方法,那么必须在init中,明确写出 self =,不然,就根本得不到正确的对象!所以说,在你不知道你的父类是否进行了这种操作时,最好使用在子类初始化时使用 self = [super init],来确保你写的子类是正确的。

    这个问题的本质,就是 init方法,不一定会使用alloc所产生的内存去初始化,它可以重新分配一块内存,初始化后返回!

  • 相关阅读:
    C#基础笔记(第二十一天)
    C#基础笔记(第十九天)
    C#基础笔记(第十八天)
    C#基础笔记(第十七天)
    C#基础笔记(第十六天)
    C#基础笔记(第十五天)
    [PyTorch 学习笔记] 6.1 weight decay 和 dropout
    PyTorch ResNet 使用与源码解析
    [PyTorch 学习笔记] 5.2 Hook 函数与 CAM 算法
    [PyTorch 学习笔记] 5.1 TensorBoard 介绍
  • 原文地址:https://www.cnblogs.com/NSong/p/6432463.html
Copyright © 2020-2023  润新知