ios OC方法调用流程(如何避免找不到方法而崩溃)

C中方法调用本质就是objc_msgSend(id target, selector)函数的调用,如果是对象方法,那么这个target是类对象;如果是类方法,则这个target是元类对象。

一,查找方法调用流程

1,按照方法名去cache_t中查找方法,找到了就直接调用。
2,1中未找到,进入类对象方法列表中查找。这个列表包含了分类的方法。
3,如果在方法列表中找到了方法,则首先将方法加入cache_t中,然后调用方法。
4,如果在方法列表中未找到方法,会通过superclass找到父类,在父类中进行1、2、3步骤。
5,如果最终未找到方法,会进入方法的动态解析阶段。

二,未找到可执行的方法

objc_msgSend ()函数调用的执行分3个阶段:

1,找到方法,消息发送。
2,方法未找到,进入动态解析流程。
3,态解析流程未处理,进入消息转发流程。

如果这3个阶段都没有处理方法调用,则会奔溃unrecognized selector send to instance...。

动态方法解析流程:

当runtime系统在Cache和类的方法列表(包括父类)中找不到要执行的方法时runtime会调用resolveInstanceMethod: 或者resolveClassMethod: 来给我们一次动态添加方法实现的机会。

1,会根据是对象方法还是类方法调用类方法resolveInstanceMethod :(SEL)sel与resolveClassMethod :(SEL)sel。
2,可以在上述方法里面动态添加方法sel的实现,这样就会调用到方法。
3,态添加的方法,先添加在类的方法列表中,之后再走的查找方法的流程,在找到方法调用之前会将方法加入到方法缓存列表cache_t中,再执行方法。
4,如果这里没有动态添加方法实现,但是返回值是YES, 就会进入消息转发阶段。

我们需要用class_addMethod函数完成向特定类添加特定方法实现的操作:

 

- (void)test_aaaaaa{
    NSLog(@"test_aaaaaa");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
   
    if (sel == @selector(test)) {
        
        Method method2 = class_getInstanceMethod(self, @selector(test_aaaaaa));
        class_addMethod(self, sel, method_getImplementation(method2), method_getTypeEncoding(method2));
        // 这里class_addMethod()中第一个参数self是类对象
        // 如果是类方法,则class_addMethod()调用时,第一个参数应该写元类对象object_getClass(self)
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}
+ (BOOL)resolveClassMethod:(SEL)sel{
    return [super resolveClassMethod:sel];
}


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中调用iOS方法需要使用JavaScript与原生iOS之间的交互技术。以下是一些方法: 1. 使用UIWebView执行JavaScript代码 可以使用UIWebView在iOS应用程序中执行JavaScript代码。UIWebView对象提供了一个方法,可以通过该方法将JavaScript代码传递给UIWebView并执行它。在JavaScript代码中,可以使用window.location来调用iOS方法。例如: ``` window.location = "ios://methodName?param1=value1&param2=value2"; ``` 在iOS应用程序中,可以在UIWebView的委托方法中截取这个请求,解析参数,并调用相应的方法。例如: ``` - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = request.URL; if ([[url scheme] isEqualToString:@"ios"]) { NSString *methodName = [url host]; NSDictionary *params = [self parseParams:[url query]]; // call the iOS method with the given name and parameters [self callMethod:methodName withParams:params]; return NO; } return YES; } ``` 2. 使用JavaScriptCore框架 JavaScriptCore框架是一个内置于iOS中的JavaScript引擎。可以使用它来执行JavaScript代码并与原生iOS进行交互。可以使用JSContext对象来将JavaScript代码传递给JavaScript引擎并执行它。在JavaScript代码中,可以使用JSContext对象的evaluateScript方法调用iOS方法。例如: ``` var methodName = "methodName"; var param1 = "value1"; var param2 = "value2"; var result = MyObjCClass.callNativeMethod(methodName, param1, param2); ``` 在iOS应用程序中,可以创建一个MyObjCClass类来处理JavaScript传递的调用请求,并返回结果。例如: ``` JSContext *context = [[JSContext alloc] init]; context[@"MyObjCClass"] = [MyObjCClass class]; [context evaluateScript:@"var methodName = 'methodName'; var param1 = 'value1'; var param2 = 'value2'; var result = MyObjCClass.callNativeMethod(methodName, param1, param2);"]; ``` 以上是两种在JavaScript中调用iOS方法方法。当然,具体的实现方案需要根据具体的需求和场景进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值