在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Objective-C Reflection(Objective-C 反射机制)
NSObject 方法 除了个别例外,Cocoa 中大部分类都是 NSObject 的子类,因此大部分对象都继承了它所定义的方法。 NSObject 提供了一些简单的查询运行时系统信息的方法:
if ([@"Hello World" isKindOfClass:[NSObject class]]) { NSLog(@"YES"); } else { NSLog(@"NO"); } if ([@"Hello World" isMemberOfClass:[NSObject class]]) { NSLog(@"YES"); } else { NSLog(@"NO"); } if ([self respondsToSelector:@selector(test)]) { NSLog(@"YES"); } else { NSLog(@"NO"); } if ([self conformsToProtocol:@protocol(NSObject)]) { NSLog(@"YES"); } else { NSLog(@"NO"); }
消息传递 在 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 实现。
定义一个 User 类 在 .h 文件,定义属性 name 以往,会在相应的 .m 文件,使用 @synthesize 声明属性 name,这样编译器会自动生成相应的 setter 和 getter 方法 但是,当使用 @dynamic 声明属性 name 时,就必须自己提供相应的 setter 和 getter 方法 Override + (BOOL)resolveInstanceMethod:(SEL)name 方法 当类实例调用 - (void)setName:(NSString) aName 或 -(NSString *)name 方法时,就为其动态地提供方法实现 #import <Foundation/Foundation.h> @interface User : NSObject { NSString *name; } @property (nonatomic, retain) NSString *name; @end
#import "User.h" #import <objc/runtime.h> @implementation User @dynamic name; - (void)dynamicSetName:(NSString *) aName { if (name != nil) { [name release]; name = nil; } [aName retain]; name = aName; } - (NSString *)dynamicName { return name; } + (BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"Instance Method: %@", NSStringFromSelector(sel)); if ([@"setName:" isEqualToString:NSStringFromSelector(sel)]) { class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicSetName:)], "v@:"); return YES; } else if ([@"name" isEqualToString:NSStringFromSelector(sel)]) { class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicName)], "@"); return YES; } return [super resolveInstanceMethod:sel]; } @end
|
请发表评论