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. 安装opensuse的笔记-重庆linux开源组织

    mate: 伙伴 matey: 融洽的, 易于亲近的. get matey with sb. poison: a. 有毒的, n.毒药/毒酒v. 下毒, 破坏, 污染 slander [ 撕烂的~~] ...

  2. 关于轻松安装LNMP和LAMP的编译环境

    http://lnmp.org/install.html 系统需求: CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian Linux系统 需要2GB以上硬盘剩余空间 1 ...

  3. Object&&String学习

    Object类 列表项 String类 常用方法 构造方法 public String() public String(byte[] bytes) public String(byte[]bytes, ...

  4. 【JavaScript】JS_Object跟Function的区别

    JS_Object和Function的区别 我们本次的解释,主要通过下图 粗看该图,估计你不一定能看明白.不过接下来让我逐行向你解释. 最左侧:意思是,有两个对象f1和f2,他们是通过new Foo( ...

  5. hiho #1326 : 有序01字符串

    #1326 : 有序01字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于一个01字符串,你每次可以将一个0修改成1,或者将一个1修改成0.那么,你最少需要修改 ...

  6. hiho #1305 区间求差

    #1305 : 区间求差 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1, A2 ], [ A3,  ...

  7. MS DOS 命令大全

    刚好看到留下来以备用: 一)MD——建立子目录命令 1.功能:创建新的子目录 2.类型:内部命令 3.格式:MD[盘符:][路径名]〈子目录名〉 4.使用说明: (1)“盘符”:指定要建立子目录的磁盘 ...

  8. BZOJ 4579: [Usaco2016 Open]Closing the Farm

    Description 依次删去一个点和它的边,问当前图是否连通. Sol 并查集. 倒着做就可以了. 每次将一个点及其的边加入,如果当前集合个数大于 1,那么就不连通. Code /******** ...

  9. echarts

    ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9/10/11 ...

  10. Python自动化之常用模块

    1 time和datetime模块 #_*_coding:utf-8_*_ __author__ = 'Alex Li' import time # print(time.clock()) #返回处理 ...