[消息传递之二]-NSMethodSignature练习

#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是能够执行这个签名的函数的对象。

你可能感兴趣的:(Objective-C,消息机制)