MXRuntimeUtils,替代 [NSObject performSelector object object ]的工具

穿山甲到底說了什麼發表於2018-12-19

程式碼demo已在Github開源, MXRuntimeUtils, 如果能幫助到您,請幫忙點個星star哈,謝謝!

MXRuntimeUtils 是用於替換 -[NSObject performSelector:object:object:]的工具,非常容易使用!

-[NSObject performSelector:object:object:] 出現哪些問題?

如果你想使用以下方法

- (id)testMethodWithIntValue:(int)aIntValue floatValue:(float)aFloatValue charValue:(char)aCharValue sizeValue:(CGSize)aCGSizeValue pointValue:(CGPoint)aCGPointValue edgeInsetsValue:(UIEdgeInsets)anUIEdgeInsetsValue stringValue:(NSString *)aStringValue idValue:(id)anIdValue {
    
    return @[@(aIntValue), @(aFloatValue), @(aCharValue), [NSValue valueWithCGSize:aCGSizeValue], [NSValue valueWithCGPoint:aCGPointValue], [NSValue valueWithUIEdgeInsets:anUIEdgeInsetsValue], aStringValue, anIdValue];
}
複製程式碼

而且你想呼叫 -[self testMethodWithIntValue:floatValue:charValue:sizeValue:pointValue: edgeInsetsValue: stringValue:idValue:]但是用另一種方式來表達 -[self performSelector:object:object:] , 你可能感到懵逼, 因為 -[NSObject performSelector:withObject:withObject:]] 最高僅僅允許傳兩個值,而且還只能是id型別,那麼,你怎麼傳基本資料型別,比如像 BOOL, char, int, float ,甚至超過兩個引數的上限呢!

//[self performSelector:@selector(testMethodWithIntValue:floatValue:charValue:sizeValue:pointValue:edgeInsetsValue:stringValue:idValue:) withObject:one withObject:two ....];
複製程式碼

如何使用

僅僅一行程式碼

[MXRuntimeUtils callMethodWithTarget:self selector:@selector(testMethodWithIntValue:floatValue:charValue:
sizeValue:pointValue:edgeInsetsValue:stringValue:idValue:) argumemts:@[@1, @2.0f, [NSNumber numberWithChar:'3'], [NSValue valueWithCGSize:CGSizeMake(4, 4)], 
[NSValue valueWithCGPoint:CGPointMake(5, 5)], [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(6, 6, 6, 6)], @"7", @"8"] returnValue:&returnValue];
複製程式碼

如果你的原始方法有一個返回值,那麼就傳一個返回值型別的指標,就像這樣,如果你的返回值是一個OC物件, 注意要傳一個 __autoreleasing 變數就像 這樣 __autoreleasing NSString stringReturnValue, __autoreleasing id idReturnValue 而不是***NSString stringReturnValue, id idReturnValue*, 理由你可以看看這篇文章 memory management

//int returnValue 
int sumReturnValue = 0;
[MXRuntimeUtils callMethodWithTarget:self selector:@selector(sumWithAnIntValue:anotherIntValue) argumemts:@[@1, @2] returnValue:&returnValue];
//sumReturnValue = 3;

//id returnValue 
__autoreleasing id idReturnValue = nil;//avoid idReturnValue is dealloc after method invoking
[MXRuntimeUtils callMethodWithTarget:self selector:@selector(ConvertIntValueToIdType:) argumemts:@[@1] returnValue:&idReturnValue];
//idReturnValue = @1;
複製程式碼

之後你就可以從sumReturnValue中得到數字3, idReturnValue中得到1

螢幕截圖

示例程式碼中的demo 截圖就像這樣, 但是你會有點疑惑,為什麼我傳的值是字元型別char 3,轉換成數字型別咋變成了51了,事實上, 在 ASCIIchar value '3' 就是 數字 51, 就像 'A'65, 'a' 是 97 一樣

執行結果

特性

  • 自動型別檢查

如果你傳一個 CGPoint型別的值給一個 宣告為int型別的方法引數,斷言會觸發,你會在Xcode控制檯中得到以下截圖資訊

  • 允許傳兩個以上的引數

  • 得到任何型別的返回值

    自動型別檢查

相關文章