NSInvocation的基本用法

@在 iOS中可以直接調用某個對象的消息方式有2種:

1.performSelector:withObject:                                         2.NSInvocation

第一種方式比較簡單,能完成簡單的調用。但是對於>2個的參數或者有返回值的處理,那就需要做些額外工作才能搞定。那麼在這種情況下,我們就可以使用NSInvocation來進行這些相對複雜的操作.

@其實也是工作所使,原先只是知道,但沒實際的用過,果然工作的時候纔會實際的區去運用各個知識點.

//
//  HMTTest1.h
//  Created by HMT on 14-8-3.
//

#import <Foundation/Foundation.h>

@interface HMTTest1 : NSObject

- (NSString *)addTestString:(NSString *)testString;

@end

//
//  HMTTest1.m
//  Created by HMT on 14-8-3.
//

#import "HMTTest1.h"

@implementation HMTTest1

- (NSString *)addTestString:(NSString *)testString{

    NSString *string = [NSString stringWithFormat:@"這是一個關於%@的測試Demo", testString];

    return string;
}

@end


- (void)testOfNSInvocation{

    /*******************************normal方式*******************************/
    HMTTest1 *test1 = [[HMTTest1 alloc] init];
    NSString *normalString = [test1 addTestString:@"直接調用方法"];
    NSLog(@"normal = %@",normalString);
    NSLog(@"normal = %@",[test1 performSelector:@selector(addTestString:) withObject:@"performSelector:withObject"]);
    
    /*******************************NSInvocation方式*******************************/
    NSString *testString = @"haha";
    // 方法簽名類,需要被調用消息所屬的類HMTTest1 ,被調用的消息addTestString:
    NSMethodSignature *signature = [[HMTTest1 class] instanceMethodSignatureForSelector:@selector(addTestString:)];
    // 根據方法簽名創建一個NSInvocation
    NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:signature];
    // 設置調用者也就是HMTTest1的實例對象,也就是test1
    [myInvocation setTarget:test1];
    // 設置被調用的消息
    [myInvocation setSelector:@selector(addTestString:)];
    // 如果此消息有參數需要傳入,參數是void*類型,需要注意的是atIndex的下標必須從2開始。原因爲:0 1 兩個參數已經被target 和selector佔用
    //id(泛型對象)和void*(泛型指針)並非完全一樣
    [myInvocation setArgument:&testString atIndex:2];
    // 定義接收結果的變量
    NSString *result = nil;
    // retain所有參數,防止參數被釋放dealloc
    [myInvocation retainArguments];
    // 消息調用
    [myInvocation invoke];
    // 將得到的結果賦值給定義的變量
    [myInvocation getReturnValue: &result];
    NSLog(@"The NSInvocation invoke string is: %@", result);
    
//    //獲得返回值類型
//    const char *returnType = signature.methodReturnType;
//    // 聲明返回值變量
//    id returnValue;
//    // 如果沒有返回值,也就是消息聲明爲void,那麼returnValue=nil
//    if( !strcmp(returnType, @encode(void)) ){
//        
//        returnValue =  nil;
//        
//    }
//    // 如果返回值爲對象,那麼爲變量賦值
//    else if( !strcmp(returnType, @encode(id)) ){
//        
//        [myInvocation getReturnValue:&returnValue];
//        
//    }
//    else{
//    
//    }
    
    /*******************************@encode(aType) 可以返回該類型的 C 字符串(char *)的表示*******************************/
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],@"key1",[NSNumber numberWithDouble:100.00f],@"key2",[NSNumber numberWithInt:200],@"key3",[NSNumber numberWithFloat:300.0f], @"key4", nil];
    for(NSString *key in dic){
        id value = [dic valueForKey:key];
        if([value isKindOfClass:[NSNumber class]]){
            const char * pObjCType = [((NSNumber*)value) objCType];
            if (strcmp(pObjCType, @encode(int))  == 0) {
                NSLog(@"字典中key=%@的值是int類型,值爲%d",key,[value intValue]);
            }
            if (strcmp(pObjCType, @encode(float)) == 0) {
                NSLog(@"字典中key=%@的值是float類型,值爲%f",key,[value floatValue]);
            }
            if (strcmp(pObjCType, @encode(double))  == 0) {
                NSLog(@"字典中key=%@的值是double類型,值爲%f",key,[value doubleValue]);
            }
            if (strcmp(pObjCType, @encode(BOOL)) == 0) {
                NSLog(@"字典中key=%@的值是bool類型,值爲%i",key,[value boolValue]);
            }
        }
        
    }

}




發佈了169 篇原創文章 · 獲贊 13 · 訪問量 87萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章