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所产生的内存去初始化,它可以重新分配一块内存,初始化后返回!

iOS self = [super init]的更多相关文章

  1. [转] "self = [super init]"的解释与潜藏bug

    Objective-C的推荐init方法写法如下: - (id) init { if(self = [super init]) { //为子类增加属性进行初始化 } return self; } 这里 ...

  2. 【iOS】swift init构造器

    这几天在使用 Swift 重写原来的一个运动社交应用 SportJoin. 为什么要重写呢? 首先因为实在找不到设计师给我作图; 其次, 我也闲不下来, 想找一些项目做, 所以只好将原来的代码重写了. ...

  3. OC self = [super init] , 点语法 , @property

    OC self = [super init] , 点语法 , @property 构造方法为啥这么写? self = [super init]; [super init] 的结果可能有三种: 第一种: ...

  4. ios initialize和init等方法

    在程序运行过程中,创建多个类对象,只会调用一次initialize  [ɪˈnɪʃəˌlaɪz] .而创建几个类对象就会调用几次init; 创建一个类aa,分别重写 initialize和init方法 ...

  5. [super init]方法的调用

    当重新覆盖父类的init方法时,需要调用[super init]方法确认父类中的init是返回一个实例,而不是一个空的实例. 那为什么要调用这个呢? 我得猜测是这样的:因为这是一个初始化方法,需要对对 ...

  6. Swift - Property ''not initialized at super.init call

    Property ''not initialized at super.init call 这个错误应该挺常见的的,为什么在百度上没有找到呢,stack over flow找到了,也不能说是什么解决办 ...

  7. 刨根问底:对于 self = [super init] 的思考

    对象初始化有两种方式:[class new] 与 [[class alloc] init] 对于后者,有分配和初始化的过程,alloc 从应用程序的虚拟地址空间上为该对象分配足够的内存,并且将新对象的 ...

  8. 关于self和super在oc中的疑惑与分析 (self= [super init])

    这个问题貌似很初级,但很容易让人忽略,me too .直到在一次面试时被问到,稀里糊涂的回答了下.实在惭愧, 面试一定都是很注重 基础的,不管高级还是初级. 虽然基础好跟基础不好都可以写代码,网上那么 ...

  9. swift中的如果在构造方法中使用KVC, 调用了super.init(), 报错, 基本数据类型属性找不到

    swift要求, 属性必须有初始化值, 如果不对其赋值, 可以加一个?系统会默认给其包装一个可选值(直说就是nil) 如果定义一个基本类型, 建议直接赋值, 不建议使用? 下面说下标题中的问题 有时候 ...

随机推荐

  1. Cucumber

    http://www.ibm.com/developerworks/library/a-automating-ria/ Cucumber is a testing framework that hel ...

  2. 修改ubuntu DNS的步骤/wget url报错: unable to resolve host address的解决方法

    wget url 报错:unable to resolve host address ‘url’,显然是无法解析主机地址,这就能看出是DNS解析的问题.解决办法就是配置可用的dns 一般是修改成为谷歌 ...

  3. jquery access方法 有什么用

    Jquery设置对象属性的有几种方法1.获取属性attr(name) 2.设置属性attr(name,value)3.批量设置属性attr(properties)4.为所有匹配的元素设置一个计算的属性 ...

  4. PHP Warning: date() [function.date]: It is not safe to rely on the system's timezone

    在用PHP5.3以上的PHP版本时,只要是涉及时间的会报一个 Warning: phpinfo() [function.phpinfo]: It is not safe to rely on the ...

  5. sql中的常见的全局变量

    select APP_NAME ( ) as w --当前会话的应用程序 select @@IDENTITY --返回最后插入的标识值 select USER_NAME() --返回用户数据库用户名 ...

  6. IIS 您要访问的网页有问题,无法显示!

    提示:您要访问的网页有问题,无法显示.HTTP 500 – 内部服务器错误.”的问题解决方案! IIS服务器出现错误的原因很多,请尝试以下操作:1.查看网站属性——文档看看启用默认文档中是否存在:in ...

  7. 用H5的canvas做时钟

    <!doctype html><html> <head> <meta charset="UTF-8"> <title>D ...

  8. ajax异步提交数据动态更改select选项

    <!DOCTYPE html> <html> <head> <title></title> <script src="../ ...

  9. Pcserver+oracle10g+rac

    成本的相对廉价,技术的成熟,功能的强大此方案将越来越受中小企业的青睐.     一.实验前准备 虚拟机版本:Vwareserver1.0.6 Linux版本:redhat5.5enterprise服务 ...

  10. iOS开发——高级篇——Objective-C特性:Runtime

    Objective-C是基于C语言加入了面向对象特性和消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和转发.下面通过分析Apple开源的 ...