#import <Foundation/Foundation.h>
@interface MyInvoc : NSObject
{
NSString* _name;
}
-(NSInteger) myLen:(NSString*) aStr;
-(NSMethodSignature*) methodSignatureForSelector:(SEL)aSelector;
-(void)forwardInvocation:(NSInvocation *)anInvocation;
@end
#import "MyInvoc.h"
@implementation MyInvoc
{
NSMutableDictionary* _dic;
}
-(id)init
{
if (self = [super init]) {
_name = [[NSString alloc] init];
_name = @"hello";
_dic = [[NSMutableDictionary alloc] init];
}
return self;
}
-(NSInteger) myLen:(NSString *)aStr
{
return [aStr length];
}
-(NSMethodSignature*) methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature* Msignature =[super methodSignatureForSelector:aSelector];
if (!Msignature) {
NSString* MethodName = NSStringFromSelector(aSelector);
if ([MethodName rangeOfString:@"set"].location == 0) {
Msignature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
//v@:@ v:返回值类型void;@ id类型,执行sel的对象;:SEL;@参数
}
else
{
if ([MethodName compare:@"length"] == NSOrderedSame) {
Msignature = [_name methodSignatureForSelector:aSelector];
}
else{
Msignature =[NSMethodSignature signatureWithObjCTypes:"@@:"];
//@:返回值类型id;@id类型,执行sel的对象;:SEL;
}
}
}
return Msignature;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
NSString* MethodName = NSStringFromSelector([anInvocation selector]);
if ([MethodName rangeOfString:@"set"].location == 0) {
NSString* key = [[MethodName substringWithRange:NSMakeRange(3, [MethodName length] - 4)] lowercaseString];
id obj;
[anInvocation getArgument:&obj atIndex:2];
[_dic setObject:obj forKey:key];
}
else{
if ([MethodName compare:@"length"] == NSOrderedSame) {
[anInvocation invokeWithTarget:_name];
}
else
{
id obj = [_dic objectForKey:MethodName];
[anInvocation setReturnValue:&obj];
}
}
}
@end
#import "ViewController.h"
#import "MyInvoc.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
id m = [[MyInvoc alloc] init];
//注意点1:执行的方法最好能找到,利用sel声明变量虽然也能用,但有警告。
[m setName: @"hello"];
NSLog(@"name is %@, length is %ld",[m name], [m length]);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
总结
1,sel与nsstring的转换系统提供了两个函数,特别方便。nsstringfromselector,nsselectorfromstring;
2,调用没有找到的函数时才会进入获取签名函数。
3,[aninvocation invokeWithTarget:_name],这里的taget是能够执行这个签名的函数的对象。