ios开发 Reflection(一)

NSObject 方法

除了个别例外,Cocoa 中大部分类都是 NSObject 的子类,因此大部分对象都继承了它所定义的方法。

NSObject 提供了一些简单的查询运行时系统信息的方法:

1 - (BOOL)isKindOfClass:(Class)aClass;
2 - (BOOL)isMemberOfClass:(Class)aClass;
3 - (BOOL)conformsToProtocol:(Protocol *)aProtocol;
4 
5 - (BOOL)respondsToSelector:(SEL)aSelector;

第1行判断instance的class类型

第2行判断Member是否属于类

第3行判断委托是否属于类

第4行判断方法是否属于类

测试

 1     //test Member
 2     BOOL bMember=[@"sName" isMemberOfClass:[self class]];
 3     BOOL bMember1=[@"sName" isMemberOfClass:[self class]];
 4     NSLog(@"bMember:%d,bMember1:%d",bMember,bMember1);
 5     
 6     //test Method
 7     BOOL bMethod=[@"showBook" isMemberOfClass:[self class]];
 8     BOOL bMethod1=[@"showBook" isMemberOfClass:[self class]];
 9     NSLog(@"bMethod:%d,bMethod1:%d",bMethod,bMethod1);
10     
11     //test Protocol
12     BOOL bProtocol=[self conformsToProtocol:@protocol(vcDelegate)];
13     NSLog(@"bprotocol:%d",bProtocol);

 

消息传递

在 Objective-C,直到运行时消息才会绑定到方法实现。

编译器把消息表达式(message expression)转换为调用 Objective-C 运行时函数 objc_msgSend

[receiver message] -> objc_msgSend(receiver, selector)

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

Sends a message with a simple return value to an instance of a class.

 

使用 objc_msgSend 函数,需要引入 Objective-C 运行时头文件:#import <objc/message.h>

[self test];
objc_msgSend(self, @selector(test));

通过定义在 NSObject 类中的方法 methodForSelector: ,你可以请求一个方法实现过程(procedure)的指针。

- (IMP)methodForSelector:(SEL)aSelector

Locates and returns the address of the receiver’s implementation of a method so it can be called as a function.

调用 IMP,头两个需要传递的参数,第一个是消息接收的对象,第二个是 selector。

IMP test = [self methodForSelector:@selector(test)];
test(self, @selector(test));

动态方法 

有些情况下,我们会想要提供动态的方法实现。

Objective-C 通过使用 @dynamic 声明属性(property)来告诉编译器,属性(property)相关的方法将会动态地提供。

你可以通过实现方法 resolveInstanceMethod: 和 resolveClassMetho: 为相应的一个实例和类方法来动态地提供一个 selector 实现。

  • + (BOOL)resolveInstanceMethod:(SEL)name
    Dynamically provides an implementation for a given selector for an instance method.

  • + (BOOL)resolveClassMethod:(SEL)name
    Dynamically provides an implementation for a given selector for a class method.

 

定义一个 User 类

在 .h 文件,定义属性 name

以往,会在相应的 .m 文件,使用 @synthesize 声明属性 name,这样编译器会自动生成相应的 setter 和 getter 方法

但是,当使用 @dynamic 声明属性 name 时,就必须自己提供相应的 setter 和 getter 方法

Override + (BOOL)resolveInstanceMethod:(SEL)name 方法

当类实例调用 - (void)setName:(NSString) aName 或  -(NSString *)name 方法时,就为其动态地提供方法实现

1 #import <Foundation/Foundation.h>
2 
3 @interface User : NSObject {
4     NSString *name;
5 }
6 
7 @property (nonatomic, retain) NSString *name;
8 
9 @end
 1 #import "User.h"
 2 #import <objc/runtime.h>
 3 
 4 @implementation User
 5 
 6 @dynamic name;
 7 
 8 - (void)dynamicSetName:(NSString *) aName {
 9     if (name != nil) {
10         [name release];
11         name = nil;
12     }
13     [aName retain];
14     name = aName;
15 }
16 
17 - (NSString *)dynamicName {
18     return name;
19 }
20 
21 + (BOOL)resolveInstanceMethod:(SEL)sel {
22     NSLog(@"Instance Method: %@", NSStringFromSelector(sel));
23     if ([@"setName:" isEqualToString:NSStringFromSelector(sel)]) {
24         class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicSetName:)], "v@:");
25         return YES;
26     } else if ([@"name" isEqualToString:NSStringFromSelector(sel)]) {
27         class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicName)], "@");
28         return YES;
29     }
30     return [super resolveInstanceMethod:sel];
31 }
32 
33 @end

 

posted on 2014-10-31 16:50  古成风云  阅读(273)  评论(0编辑  收藏  举报

导航