连载三---探索Objc/Runtime

当人们初学 Cocoa/Objective-C 时,Objective-C Runtime 是被忽略的特性之一。原因是 Objective-C(这门语言)很容易在几小时内就熟悉,新学 Cocoa 的人花费他们大部分的时间学习 Cocoa 框架和适应它是如何工作的。然而每个人至少应该知道一些 runtime 的工作细节,需要比知道编译器会把 [target doMethodWith:var1];  转换为 objc_msgSend(target,@selector(doMethodWith:),var1); 更深入一些。知道 Objective-C 正在做的会让你更深入的理解 Objective-C 和你正在运行的 app。我认为 Mac/iPhone 的开发者不管你现在是什么水平,都会有收获的。

Objective-C Runtime 是什么?

Objective-C 的 Runtime 是一个运行时库(Runtime Library),它是一个主要使用 C 和汇编写的库,为 C 添加了面相对象的能力并创造了 Objective-C。这就是说它在类信息(Class information) 中被加载,完成所有的方法分发,方法转发,等等。Objective-C runtime 创建了所有需要的结构体,让 Objective-C 的面相对象编程变为可能。


动态 vs 静态语言
Objective-C 是面相运行时的语言(runtime oriented language),就是说它会尽可能的把编译和链接时要执行的逻辑延迟到运行时。这就给了你很大的灵活性,你可以按需要把消息重定向给合适的对象,你甚 至可以交换方法的实现,等等。这就需要使用 runtime,runtime 可以做对象自省查看他们正在做的和不能做的(don't respond to)并且合适的分发消息.

Objective-C Runtime 术语
更深入之前,咱们先了解点术语。Mac 和 iPhone 开发者关心的有两个 runtime:Modern Runtime(现代的 Runtime) 和 Legacy Runtime(过时的 Runtime)。Modern Runtime:覆盖所有 64 位的 Mac OS X 应用和所有 iPhone OS 的应用。 Legacy Runtime: 覆盖其他的所有应用(所有 32 位的 Mac OS X 应用) Method 有 2 种基本类型的方法。Instance Method(实例方法):以 ‘-’ 开始,比如 -(void)doFoo; 在对象实例上操作。Class Method(类方法):以 ‘+’ 开始,比如 +(id)alloc。方法(Methods)和 C 的函数很像,是一组代码,执行一个小的任务.

一. 属性声明(Declare Properties)
// 如果可以在 runtime 的时候获得类的属性,这将会很有用处,比如对 json 数据序列化。
runtime 提供了相应的函数来实现:
    unsigned int propertyCount = 0 ;

   
objc_property_t *propertyArray = class_copyPropertyList ([ UIView class ], &propertyCount);

   
NSLog ( @"property of UIView : " );

   
for ( int i = 0 ; i < propertyCount; i++) {

       
objc_property_t property = propertyArray[i];

       
fprintf ( stdout , "%s:%s\n" , property_getName (property), property_getAttributes (property));

    }

    propertyCount = 0 ;

    propertyArray =
class_copyPropertyList ([ UILabel class ], &propertyCount);

   
NSLog ( @"property of UILabel : " );

   
for ( int i = 0 ; i < propertyCount; i++) {

       
objc_property_t property = propertyArray[i];

       
fprintf ( stdout , "%s:%s\n" , property_getName (property), property_getAttributes (property));

    }

//runtime 只会获取当前类的属性 —— 父类的以及扩展里实现的属性都不能通过这样的方式获取。

二. 方法的动态实现(Dynamic Method Resolution)
我们给类在runtime添加方法。比如,objc中有dynamic的属性关键字(使用过coredata的都知道),这个就提示该属性的方法在运行时提供。
#import "TestObject.h"

@implementation TestObject

// 方法的动态实现( Dynamic Method Resolution

@dynamic testUrl;

//C 语言函数 ( 方法 )
void dynamicMethod( id self , SEL _cmd , float w){
   
   
printf ( " 执行 Set 方法 !\n" );
   
}

+ (
BOOL )resolveInstanceMethod:( SEL )sel{
   
   
NSString *methodName = NSStringFromSelector (sel);
   
   
if ([methodName isEqualToString : @"setTestUrl:" ]) {
       
       
class_addMethod ([ self class ], sel, ( IMP ) dynamicMethod , "v@:f" );
       
       
return YES ;
       
    }
   
   
return [ super resolveInstanceMethod :sel];
}

/*
    Objective-C
程序可以在运行时链接新的类和 categary. 动态加载可以用来做很多不同的事情 .
 
*/

三. 动态加载(Dynamic loading)

(这部分主要侧重于Mac OS 系统) 我们知道category是在第一次使用到的时候添加到class的,因此objc也提供了动态添加class的机制。比如OS的系统偏好里的一些设置就是通过动态添加实现的,当然还有插件系统。 runtime提供了相应的函数(objc/objc-load.h),但对于cocoa系统,我们可以使用NSBundle来更好的操作。下面简单的说一下步骤:
1. 新建一个cocoa的工程,选择bundle模板;
2. 新建一个class,然后添加一个方法并实现之;
3. 修改plist文件,在principle class一行将新建的class名填进去;
4. build工程,然后在Finder里找到bundle;
5. 新建一个测试bundle的工程,模板任选(可以选择application)
6. 把之前的bundle文件添加的测试工程,然后添加相应的代码:

#import "AppDelegate.h"

@interface AppDelegate ()

@property ( weak ) IBOutlet NSWindow *window;
@end

@implementation AppDelegate

- (
void )applicationDidFinishLaunching:( NSNotification *)aNotification {
   
// Insert code here to initialize your application
   
   
NSString *bundlePath = [[ NSBundle mainBundle ] pathForResource : @"Test" ofType : @"bundle" ];
   
NSBundle *bundle = [ NSBundle bundleWithPath :bundlePath];
   
if (bundle)
    {
        Class principleClass = [bundle
principalClass ];
       
if (principleClass)
        {
           
id bundleInstance = [[principleClass alloc ] init ];
            [bundleInstance
performSelector : @selector (nslog) withObject : nil withObject : nil ];
        }
    }
  
}

经过简单的研究runtime,我逐渐意识到了,runtime的强大,由于时间有限,再加上我本身技能也不是太强,我也不能对其研究的太好,不足之处还望谅解,如果大家有兴趣的话,可以先在苹果官方开源类库里先把objc/runtime的.mm文件下载下来,对照着研究,并且参考下面几个文档:

Objective-C Runtime 运行时之三:方法与消息:

http://www.cocoachina.com/ios/20141106/10150.html


刨根问底ObjectiveC Runtime

http://www.cocoachina.com/ios/20141224/10740.html


Objc-Runtime分析

http://www.tekuba.net/program/340/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值