对象初始化有两种方式:[class new] 与 [[class alloc] init]

对于后者,有分配和初始化的过程,alloc 从应用程序的虚拟地址空间上为该对象分配足够的内存,并且将新对象的引用计数加1、将对象的成员变量初始为零,init 会做真正的初使化工作,为对象的实例变量赋予合理有用的值。

一般不推荐使用[class new],而推荐使用[[class alloc] new],查看源码分析一下:

+ new
{ id newObject = (*_alloc)((Class)self, 0); Class metaClass = self->isa; if (class_getVersion(metaClass) > 1) return [newObject init]; else return newObject;
} //而 alloc/init 像这样:
+ alloc
{ return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{ return self;
}

发现[class new]默认调用 alloc与init方法,那么我们无法使用自定义的初始化方法,多了更多的局限性。那么[class alloc] init] 会更方便, 当然[class alloc] init] 的设计也是由于历史的原因。

为啥这么写?

- (instancetype)init
{if (self = [super init]) {// Custom initialization
    }return self;
}

我们知道alloc返回一个有效的未初始化的对象实例。对于self是alloc 返回的指针,同时可以在所有的方法作用域内访问。

但是对于 super,它只是一个”编译器指示符”,告诉编译器在父类中搜索方法的实现。

优先调用[super init] 是为了使超类完成它们自己的初始化工作。

那么 if (self = [super init])又是做啥?

这里是担心父类初始化失败,如果初始化一个对象失败,就会返回nil,当返回nil的时候self = [super init]测试的主体就不会再继续执行。如果不这样做,你可能会操作一个不可用的对象,它的行为是不可预测的,最终可能会导致你的程序崩溃。

理解 Self & Super

看到网上一道经典的题目:

@implementation Son : Father
- (id)init
{self = [super init];if (self){NSLog(@"%@", NSStringFromClass([self class]));NSLog(@"%@", NSStringFromClass([super class]));}return self;
}
@end

self表示当前这个类的对象,而super是一个编译器标示符,和self指向同一个消息接受者。在本例中,无论是[self class]还是[super class],接受消息者都是Son对象,但super与self不同的是,self调用class方法时,是在子类Son中查找方法,而super调用class方法时,是在父类Father中查找方法。

当调用[self class]方法时,会转化为objc_msgSend函数,这个函数定义如下:

id objc_msgSend(id self, SEL op, ...)

这时候就开始了消息传递和转发的过程,会先从Cache 中查找方法,然后当前类,如果还是查找不到会去父类,直至NSObject类

对于NSObject类中,- (Class)class的实现如下:

- (Class)class {  return object_getClass(self);
}

所以打印结果为Son

当调用[super class]方法时,会转化为objc_msgSendSuper,这个函数定义如下:

id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

objc_msgSendSuper函数第一个参数super的数据类型是一个指向objc_super的结构体

struct objc_super {__unsafe_unretained id receiver;__unsafe_unretained Class super_class;
};

结构体包含两个成员,第一个是receiver,表示类的实例。第二个成员是记录当前类的父类是什么,会优先从Father这个类里去找- (Class)class,然后进行消息传递的过程。

会发现不管是self、还是super指向消息接受者是一样的,并且经过消息传递,最终处理消息的方法都是NSObject中的- (Class)class方法。
参考文章:

Objective-C Runtime

http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/#objc_msgSend%E5%87%BD%E6%95%B0

深入理解Objective-C的Runtime机制

http://www.csdn.net/article/2015-07-06/2825133-objective-c-runtime/1

What exactly is super in Objective-C?

http://stackoverflow.com/questions/3095360/what-exactly-is-super-in-objective-c

刨根问底:对于 self = [super init] 的思考相关推荐

  1. self = [super init]

      父类进行初始化时,用的是子类对象指针self,父类的init方法有可能对这个指针指向的内存区作了大的变更(有可能把这个指针所指的内存释放了,重新分配了另一块内存区域返回来,这时这个返回的指针与原来 ...

  2. 关于pytorch中super的一点思考,结合代码

    class ResidualAdd(nn.Module):def __init__(self, fn):super().__init__()#inherit fa class's init metho ...

  3. 【转】[iOS] 关于 self = [super init];

    http://blog.csdn.net/wihing/article/details/7316041 转载于:https://www.cnblogs.com/ygm900/archive/2013/ ...

  4. 刨根问底Objective-C Runtime(1)- Self Super

    转:http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective%5Bnil%5Dc-runtime(1)%5Bnil%5D-self-and-s ...

  5. alloc、init你弄懂50%了吗?

    前言 这是一篇我记录对alloc.init分析思考的笔记.如果读者想看懂我的第二个思考,可能需要您至少了解内存的分段分页管理,如果您对其一点都不知道,可以先看这篇软文简单了解一下.另外很重要的一点是, ...

  6. Objective-C:OC内部可变对象和不可变对象的深(复制)拷贝问题思考:

    OC内部:可变对象和不可变对象的深(复制)拷贝问题思考: 不可变对象: 例如NSString对象,因为NSString对象是常量字符串,所以,不可以更改其内容,但是可以修改指向该字符串的指针指向.当对 ...

  7. IOS-RunTime(刨根问底)

    方法调用 让我们看一下方法调用在运行时的过程(参照前文类在runtime中的表示) 如果用实例对象调用实例方法,会到实例的isa指针指向的对象(也就是类对象)操作. 如果调用的是类方法,就会到类对象的 ...

  8. 刨根问底Objective-C Runtime

    该笔记分为四篇: 刨根问底Objective-C Runtime(1)- Self & Super 刨根问底Objective-C Runtime(2)- Object & Class ...

  9. alloc、init 详解

    原文地址 http://ios.jobbole.com/86324/   感谢作者 前言 这是一篇我记录对alloc.init分析思考的笔记.如果读者想看懂我的第二个思考,可能需要您至少了解内存的分段 ...

最新文章

  1. ntohs的一个简单实现(将网络流中用两个字节16进制表示的资源数(如DNS)和长度转换为整形)...
  2. timestamp的两个属性:CURRENT_TIMESTAMP 和ON UPDATE CURRENT_TIMESTAMP
  3. UltraVNC反向连接方式的使用
  4. 第一次失效_神兵小将:净化之力失效地魔兵兽,全靠特殊办法,铁心方式真霸气...
  5. $.ajax()参数详解及标准写法
  6. android webview url scheme,Android Webview ERR_UNKNOWN_URL_SCHEME错误
  7. 17.立体匹配——匹配两个图 Matlab实战,立体效果_3
  8. 蔬菜基地售卖系统stage1
  9. 用python编程输入三角形的三条边判断是否构成三角形_vb三角形编程输入三条边,判断能否构成三角形.看我的编程是否有问题,...
  10. 一个批量转换文件编码的python脚本
  11. iOS开发之获取当前手机语言
  12. 工业设计三维软件有哪些?
  13. 【STL】C++ STL超全总结
  14. Linux下deb包和rpm包区别
  15. 饿了么美团外卖cps返利系统外卖返利公众号搭建cps系统小程序SaaS源码
  16. 【运放学习】:虚短、虚短、虚地、深度负反馈
  17. STM32F10xxx20xxx21xxxL1xxxx Cortex-M3程序设计手册 阅读笔记四(5):系统滴答定时器
  18. 认识 DELL EMC VPLEX VS6物理配置
  19. 您是否在找这样的软件:
  20. mysql 一边查询一边删除和一边新增一边查询判断所导致的问题

热门文章

  1. adb查看activity的堆栈信息
  2. 递推DP URAL 1119 Metro
  3. 利用ettercap进行简单的基于数据库的ARP毒化攻击
  4. 8 mv命令_Linux常用操作命令——文件和目录操作
  5. Linux内核中的proc文件系统
  6. ajax返回值demo
  7. 自学篇之----html的所有input标签 以及post和get提交之间的区别
  8. 测测实际带宽,预防使用“假带宽”
  9. mysql 80070057_返回E_INVALIDARG (0x80070057)
  10. 华为 该软件被检测为风险软件_美团被华为标记为“病毒软件”,用户表示懵了,华为官方出面解释...