Objective-C Runtime基础

一.Class

在Objective-C的runtime中有个类型是Class(只在Runtime环境中使用),用来表示Object-C中的类,定义为:

Class类型是一个指针,指向struct objc_class,而struct objc_class才是保存真正数据的地方,再看struct objc_class的声明

struct objc_class {

         Class isa;

#if !__OBJC@__

         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 *protocls

#endif

 

}OBJC2_UNAVAILABLE;

 

二.Method

是runtime内部定义的方法,用来代表一个方法:

typedef struct objc_method *Method;

struct objc_method的声明如下:

struct objc_method {

         SEL method_name

         char *method_types

         IMP method_imp

}

SEL和IMP代表什么? 

1.根据Class和Method的定义来理解Objcetive-C中的消息机制:

1)objc_class中method list在新runtime里的定义:

typedef struct method_list_t {

         uint32_t entsize_NEVER_USE;

         uint32_t count;

         struct method_t first ;

}method_list_t;

 

typedef struct method_t {

         SEL name ;

         const char *types;

         IMP imp;

}method_t ;

SEL相当于char*,可以认为objc_class中method list保存了一个SEL<->IMP的映射

 

调用一个类方法[bird fly];

其中对fly的调用,其实是由编译器出入了一段代码,根据SEL找到IMP(fly就是方法名SEL),从而进行调用,插入的代码如下

runtime中msg相关函数

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

这个函数发送消息给theReceiver,并将返回返回值.编译器其实是将[bird fly]转化成对objc_msgSend的调用,从而实现消息机制.objec_msgSend()函数将会使用theReciver的isa指针来找到theReceiver的类空间结构,并在类空间结构中查找theSelector所对应的方法.如果没有找到,那么将使用父类的指针(指向父类的isa指针)找到父类空间结构进行theSelector的查找.如果仍然没找到,就继续去父类的父类一直到,一直到找到或者找到NSObjcet,有则调用,没有则报错undefind.

 

三.Ivar

Ivar(instance variable)(实例变量,跟某个对象关联,不能被静态方法使用,与之对应的是class variable)声明如下:

typedef struct objc_ivar *Ivar ;

struct objc_ivar声明如下:

struct objc_ivar {

         char *ivar_name

         char *ivar_type

         int ivar_offset

#ifdef __LP64__

         int space

#endif

}

 

 

四.Cagegory使用场景

Runtime中用来表示Category的声明为:

typedef struct objc_category *Category;

struct objc_category的定义为runtime.h文件中

Category可以动态地为已经存在的类添加新的行为.这样可以保证类的原始设计规模较小,功能增加时再逐步扩展.使用Category对类进行扩展式,不需要访问其源码,也不需要创建子类.Category使用简单的方式,实现了类的相关方法的模块化,把不同的类方法分配到不同的分类文件中.

例子:

SomeClass.h

@interface SomeClass : NSObjcet {

}

- (void)print

@end

这是类SomeClass的声明文件,其中包含方法print.如果我们不想修改原始类,也不需要添加子类的情况下,为该类增加一个hello 方法,只需要简单的定义两个文件SomeClass+Hello.h/.m,在声明文件中用"()"把Category的名称括起来.

声明如下:

#Import "SomeClass.h"

@interface SomeClass (Hello)

- (void)hello ;

@end

实现文件如下:

#Import "SomeClass+Hello.h"

@implementationSomeClass (Hello)

- (void)hello {

         NSLog(@"name:%@",@"Jcaky");

}

@end

Hello是Category的名称,用原类名+Category的方式命名

#Import "SomeClass+hello.h"

SomeClass * sc = [[SomeClass alloc]init];

[sc hello];

 

 

  1. 当定义类的时候,在某些情况下(例如需求变更),可能想要为其中某个类或几个类中添加方法.
  2. 一个类中包含许多不同方法需要实现,而这些方法需要不同团队的成员实现.
  3. 当在使用基础类库中的类时,可能希望这些类实现一些你需要的方法

遇到以上这些需求,category可以帮助你解决问题.使用Category也有些问题需要注意

  1. Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类.
  2. Category可以重载原始类的方法,但不推荐这么做,这么做的后果是你再也不能访问原来的方法.如果确实要重载,正确的选择是创建子类.
  3. 和普通接口所有区别的是,在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它.

 

五.SEL

Runtime中用来表示一个method selector,也是一个结构体

六.IMP

IMP是一个函数指针,每一个方法都有一个对应的IMP指针指向方法实现为:

id (*IMP)(id, SEL, ...)

其所指向的方法,返回一个id,需要传入的第一个参数是self(指向某个对象,或者一个类),第二个参数是方法的SEL.(objc_property_t、objc_method_list、objc_cache、objc_protocol_list)

1.Method Swizzing 

void method_exchangeImplementations(Method m1, Method m2)

对系统方法进行替换实现一些特殊需求,运用到Category重写原始方法会覆盖的特性

配置运行时:

1)实例方法的替换:

load方法只会在程序启动时调用一次,可以不用单例

或用block实现(可不对builtsetting中的进行配置,直接调用)

2)类方法的替换

七.id

在Objective-C中id类型的对象可以转换为任何一种对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值