iOS 函式呼叫的流程
阿新 • • 發佈:2018-11-01
OC是一門動態語言,一個函式是由一個selector(SEL),和一個implement(IML)組成的。selector相當於地址,而implement才是真正的房間。和我們網購一樣,地址可以隨意寫。但不一定都能找到收件人。如果找不到系統會給程式幾次機會來使程式正常執行,之後依然不行才會丟擲異常。
下面用程式碼來實際演示一下。建議每個方法都打上斷點,這樣能夠理解函式的執行順序。
#import "RunTimeTest.h" #import <objc/runtime.h> @interface RunTimeChild : NSObject @end @implementation RunTimeChild - (void)resolveThisMethodDynamically2 { NSLog(@"resolveThisMethodDynamically"); } @end @interface RunTimeTest() @end @implementation RunTimeTest @dynamic name ,age; - (id)init { if (self = [super init]) { _mutableDic = [NSMutableDictionary dictionary]; [_mutableDic setObject:@"bnm" forKey:@"uio"]; [_mutableDic setObject:@"xiaoming" forKey:@"name"]; } return self; } void dynamicMethodIMP(id self,SEL _cmd) { NSLog(@"dynamicMethodIMP"); } /* * 這個函式在當前類執行時沒有找到對應的SEL的IML時就會執行,這個函式是給類利用class_addMethod動態新增函式的機會 * 如果實現了新增函式程式碼則返回YES,否則返回NO。 * 提醒下這裡是否繼續執行之後的流程不是以resolveInstanceMethod返回值為準的,而是以是否找到對應SEL為標準 */ + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(resolveThisMethodDynamically)) { class_addMethod([self class], sel, (IMP)dynamicMethodIMP, "
[email protected]:"); } return YES; } /* 執行到這個函式,系統將給了個將這個SEL轉給其他物件的機會 返回引數一個物件,如果這個物件非空,非self,系統會將執行的訊息轉發給這個物件執行。 */ - (id)forwardingTargetForSelector:(SEL)aSelector { RunTimeChild *child = [[RunTimeChild alloc] init]; //return child; //取消註釋會將SEL轉移至這個物件中 return nil; } /* 這個函式與forwardInvocation是最後尋找SEL的機會。這個函式讓過載方有機會丟擲一個函式的簽名,再由後面的forwardInvocation去執行 */ - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSString *sel = NSStringFromSelector(aSelector); if ([sel rangeOfString:@"set"].location == 0) { return [NSMethodSignature signatureWithObjCTypes:"[email protected]:@"]; }else{ return [NSMethodSignature signatureWithObjCTypes:"@@:"]; } } - (void)forwardInvocation:(NSInvocation *)anInvocation { NSString *key = NSStringFromSelector([anInvocation selector]); if ([key rangeOfString:@"set"].location == 0) { key = [[key substringWithRange:NSMakeRange(3, [key length] - 4)] lowercaseString]; NSString *obj; [anInvocation getArgument:&obj atIndex:2]; NSLog(@"%@",obj); [_mutableDic setObject:obj forKey:key]; }else{ NSString *obj = [_mutableDic objectForKey:key]; NSLog(@"%@",key); [anInvocation setReturnValue:&obj]; } } @end
呼叫方法:
#import "ViewController.h"
#import "RunTimeTest.h"
#import <objc/runtime.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
RunTimeTest *runTime = [[RunTimeTest alloc] init];
// SEL S = NSSelectorFromString(@"uio");
runTime.age = @"18";
NSString *f = [runTime age];
NSLog(@"%@",f);
// objc_msgSend((id)runTime,S);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
程式碼下載:http://download.csdn.net/detail/qqmcy/9450669