黑马程序员技术交流社区

标题: iOS中Cocoa框架·Runtime及isa指针知识·填坑 [打印本页]

作者: Simpon    时间: 2016-10-11 15:45
标题: iOS中Cocoa框架·Runtime及isa指针知识·填坑
本帖最后由 Simpon 于 2016-10-19 11:32 编辑

原文出处:http://www.jianshu.com/p/76992dab5936
Cocoa框架是iOS应用程序的基础,了解Cocoa框架,对开发iOS应用有很大的帮助。
1、Cocoa是什么?Cocoa是OS X和 iOS操作系统的程序的运行环境。
是什么因素使一个程序成为Cocoa程序呢?不是编程语言,因为在Cocoa开发中你可以使用各种语言;也不是开发工具,你可以在命令行上就可以创建Cocoa程序。Cocoa程序可以这么说,它是由一些对象组成,而这些对象的类最后都是继承于它们的根类 :NSObject。而且它们都是基于Objective-C运行环境的。
1.1、Cocoa框架iOS中,Cocoa众多框架中最重要最基本的两个框架是:Foundation 和 UIKit。
Foundation 和界面无关,也可以说和界面无关的类基本是Foundation框架的,和界面相关的是UIKit框架。
这两个框架在系统中处于的位置如图:



1.2、Foundation框架好吧,那我们看看两个框架的类组织架构图,第一个先看Foundation的,三个图,包括了Foundation所以的类,图中灰色的是iOS不支持的,灰色部分是OS X系统的。








将上图Foundation框架中的类进行逻辑分类如下:
1.3 UIKit框架应用程序可以通过三种方式使用UIKit创建界面
框架类组织架构图:



在图中可以看出,responder 类是图中最大分支的根类,UIResponder为处理响应事件和响应链 定义了界面和默认行为。当用户用手指滚动列表或者在虚拟键盘上输入时,UIKit就生成时间传送给UIResponder响应链,直到链中有对象处理这个事件。相应的核心对象,比如:UIApplication  ,UIWindow,UIView都直接或间接的从UIResponder继承。
2、Cocoa对象2.1 Objective-C是面向对象的语言Objective-C和Java C++一样,有封装,继承,多态,重用。但是它不像C++那样有重载操作法、模版和多继承,也没有Java的垃圾回收机制。
2.2 Objective-C的优点Objective-C语言有C++ Java等面向对象的特点,那是远远不能体现它的优点的。Objective-C的优点是它是动态的。动态能力有三种:
2.3 动态能力相关的isa指针每个Objective-C对象都有一个隐藏的数据结构,这个数据结构是Objective-C对象的第一个成员变量,它就是isa指针。这个指针指向哪呢?它指向一个类对象(class object  记住它是个对象,是占用内存空间的一个变量,这个对象在编译的时候编译器就生成了,专门来描述某个类的定义),这个类对象包含了Objective-C对象的一些信息(为了区分两个对象,我把前面提到的对象叫Objective-C对象),包括Objective-C对象的方法调度表,实现了什么协议等等。这个包含信息就是Objective-C动态能力的根源了。
那我们看看isa指针类型的数据结构是什么样的?如果抛开NSObject对象的其他的成员数据和变量,NSObject可以看成这样:
[Objective-C] 纯文本查看 复制代码
@interface NSObject <NSObject> {
     Class isa;
}

不考虑@interface关键字在编译时的作用,可以把NSObject更接近C语言结构表示为:
[Objective-C] 纯文本查看 复制代码
struct NSObject{
    Class isa;
  }

Class是用typedef定义的
[Objective-C] 纯文本查看 复制代码
typedef struct objc_class *Class;

那NSObject可以这么写了
[Objective-C] 纯文本查看 复制代码
struct NSObject{
  objc_class *isa
}

其中objc_class的结构是什么样的呢?大概是这样的:
[Objective-C] 纯文本查看 复制代码
struct objc_class {  
     Class isa;  

     Class super_class;  

     const char *name;  

     long version;  
     long info;  

     long instance_size;  
     struct objc_ivar_list *ivars;  
     struct objc_method_list **methodLists;   

     struct objc_cache *cache;  
     struct objc_protocol_list *protocols;     
}

这里会看到,在这个结构体里还有一个isa指针,又是一重指向,是不是有种到了盗梦空间的感觉。不用紧张,take easy,不会有那么多层次的,这里的isa指针指向的是元类对象(metaclass object),带有元字,证明快到头了。那元类对象有啥用呢?它用来存储的关于类的版本,名字,类方法等信息。所有的元类对象(metaclass object)都指向NSObject的元类对象,到头还是NSObject。一共三次:类对象->元类对象->NSObject元类对象。
为了得到整个类组织架构的信息,objc_class结构里定义了第二个成员变量Class super_class,它指向父类的类对象。说了这么多,可能关系缕不清楚,有道是一张图胜过千言万语:


图中可以看出,D3继承D2,D2继承D1,D1最终继承NSObject。下图从D3的一个对象开始,排列出D3 D2 D1 NSObject 类对象,元类对象等关系。



图中的箭头都是指针的指向。
2.4 根类 NSObjectNSObject是大部分Objective-C类的根类,它没有父类。其它类继承NSObject,访问Objective-C运行时系统的基本接口,这样其他类的实例可以获得运行时的能力。



2.4.1 根类和根类协议NSObject不但是个名,NSObject也是个协议的名称,参考NSObject协议 , NSObject协议指定了根类必须实现的接口。
2.4.2 根类的主要方法:
NSObjec有很多方法可以查询对象的运行时信息。这些内省方法有助于找出对象在类层次中的位置,确定对象是否实现特定的方法,以及测试对象是否遵循某种协议。下面是部分方法:
下面的方法和对象的编解码(作为归档过程的一部分)有关:
encodeWithCoder:和initWithCoder:是NSCoding协议仅有的方法。前者使对象可以对其实例变量进行编码,后者则使对象可以根据解码过的实例变量对自身进行初始化。
NSObject类中声明了一些于对象编码有关的方法:
classForCoder:、replacementObjectForCoder:、和awakeAfterUsingCoder:。
forwardInvocation:允许一个对象将消息转发给另一个对象。
在performSelector开头的一些方法允许你延迟后派发指定消息,而且可以将消息(同步或异步的消息)从辅助线程派发到主线程。
2.5 Cocoa对象生命周期对象的四种内存管理方式,如下图所示












参考:
1.http://algorithm.com.au/downloads/talks/objective-c-internals/objective-c-internals.pdf
2.http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/Introduction/Introduction.html
3.http://www.cnblogs.com/csutanyu/archive/2011/12/12/Objective-C_memory_layout.html


精华推荐:
黑马程序员:为苹果与iOS开发者的前景正名
与君共勉 --- 记黑马22期同学成长经验。
【持续更新】2016年最全最新的iOS视频+软件+源码+面试/技术
关于iOS 10最新的课程视频及demo第三弹,火速发布了







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2