您的位置:首页 > 其它

连载三---探索Objc/Runtime

2015-06-07 11:08 225 查看
当人们初学 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([UIViewclass],
&propertyCount);

   
NSLog(@"property of UIView : ");

   
for (inti =
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([UILabelclass],
&propertyCount);

   
NSLog(@"property of UILabel : ");

   
for (inti =
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"

@implementationTestObject

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

@dynamictestUrl;

//C语言函数(方法)
voiddynamicMethod(idself,SEL_cmd,floatw){

   

   
printf("执行Set方法!\n");

   

}

+ (BOOL)resolveInstanceMethod:(SEL)sel{

   

   
NSString *methodName =NSStringFromSelector(sel);

   

   
if ([methodName
isEqualToString:@"setTestUrl:"]) {

       

       
class_addMethod([selfclass],
sel, (IMP)dynamicMethod,"v@:f");

       

       
return
YES;

       

    }

   

   
return [superresolveInstanceMethod: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"

@interfaceAppDelegate()

@property(weak)IBOutletNSWindow*window;
@end

@implementationAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{

    // Insert code here to initialize your application

   

   
NSString *bundlePath = [[NSBundlemainBundle]pathForResource:@"Test"ofType:@"bundle"];

   
NSBundle *bundle = [NSBundlebundleWithPath:bundlePath];

   
if (bundle)

    {

        Class principleClass = [bundle
principalClass];

       
if (principleClass)

        {

           
id bundleInstance = [[principleClassalloc]init];

            [bundleInstance
performSelector:@selector(nslog)withObject:nilwithObject:nil];

        }
    }
  
}

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

Objective-C Runtime 运行时之三:方法与消息:
http://www.cocoachina.com/ios/20141106/10150.html
刨根问底Objective-C Runtime
http://www.cocoachina.com/ios/20141224/10740.html
Objc-Runtime分析
http://www.tekuba.net/program/340/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: