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
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。