# UIWebView article

  • OC call JS

1. Call after the webView is loaded:

/ / call the js jsFun method in the oc, and incoming parameters "hi, js" self. WebView stringByEvaluatingJavaScriptFromString: @"jsFun('hi,js')"];
Copy the code
  1. Called after the webView is loaded by JavaScriptCore (this method needs to import the JavaScriptCore framework) :
JSContext * JSContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext = jsContext; Self.jscontext evaluateScript:@"var arr = [3, 'Cooci', 'abc'];"];
Copy the code

You can also use this way:

// Convert the js method to a JSValue object and then call and pass the argument JSValue * value = self.jsContext[@"jsFun"];
  
    dispatch_async(dispatch_get_main_queue(), ^{
           [value callWithArguments:@[@"hi"The @"js"]];
     });
Copy the code
  • 1. Intercept the custom scheme in the webView proxy
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    
    NSLog(@"% @",request.URL.scheme); // identify our own protocol NSLog(@"% @",request.URL.host); // The method name is NSLog(@"% @",request.URL.pathComponents); NSString *scheme = request.url.scheme; NSString *scheme = request.url.scheme;if ([scheme isEqualToString:@"custom"]) {
        NSLog(@"Here we go. Our custom protocol."); NSArray *args = request.URL.pathComponents; NSString *methodName = args[1]; // Method 1 //if ([methodName isEqualToString:@"getSum"]) { // [self getSum]; MethodSel = NSSelectorFromString(methodName);if ([self respondsToSelector:methodSel]) {
#pragma clang diagnostic push// Tell the compiler to ignore errors#pragma clang diagnostic ignored "-Warc-performSelector-leaks"// Let the compiler go off the stack, restore the state, and continue compiling the following code! [self performSelector:methodSel withObject:args[2]];#pragma clang diagnostic pop} objc_msgSend(self,methodSel,args[2],args[3]); ((void (*) (id, SEL, id))(objc_msgSend))(self, methodSel,args[2]); Void (*kc_msgSend) (id, SEL, id)) void (*kc_msgSend) (id, SEL, id) = (void *)objc_msgSend; kc_msgSend(self,methodSel,args[2]);returnNO; }}Copy the code
  1. You can also use JavaScriptCore
// Implement the jsFun method [JSContext currentContext] in js to avoid repeating references to self.jsContext[@"jsFun"] = ^() {
        
        NSArray *args = [JSContext currentArguments];
        NSLog(@"args:%@",args); // Get NSDictionary *dict = @{@ from the js"name": @"cooci"The @"age": @}; Dispatch_async (dispatch_get_main_queue(), ^{[[JSContext currentContext][@"jsFun"] callWithArguments:@[dict]];
 });
    }
Copy the code

Other uses of JavaScriptCore:

#####JS can directly call the object method of OC: create a protocol in OC, and follow the JSExport protocol, create an object, follow the protocol

@protocol JSObjectProtocol <JSExport> - (void)hello; // Is a shorthand for a method. JSExportAs(getSum, -(int)getSumWithFirst (int)a second (int)b third (int)c); JSExportAs(getSum, -(int)getSumWithFirst (int)a second (int)b third (int)c); @end @interface JSObject : NSObject<JSObjectProtocol> @end @implementation JSObject - (void)hello { NSLog(@"hello");
}

- (int)getSumWithFirst:(int)a second:(int)b third:(int)c {
    return a+b+c;
}
@end

Copy the code

Use:

//OC bind JSObject * JSObject = [[JSObject alloc] init]; self.jsContext[@"jsObject"] = jsObject; Jsobject.hello () jsobject.getsum (1,2,3)Copy the code

#####JS exception handling:

    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        context.exception = exception;
        NSLog(@"exception == %@",exception);
        NSLog(@"% @",context);
    };
Copy the code

WKWebView article

  • OC call JS
    NSString *jsStr = [NSString stringWithFormat:@"showAlert('%@')"The @"Successful landing."];
    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@----%@",result, error);
    }];
Copy the code
  • JS calls OC 1. Similar to UIWebView, by intercepting
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSURL *URL = navigationAction.request.URL;
    NSString *scheme = [URL scheme];
    if ([scheme isEqualToString:@"custom"]) {
        NSString *host = [URL host];
        if ([host isEqualToString:@"jsCallOC"]) {
            NSMutableDictionary *temDict = [self decoderUrl:URL];
            NSString *username = [temDict objectForKey:@"username"];
            NSString *password = [temDict objectForKey:@"password"];
            NSLog(@"% @ % @" -- -,username,password); } in uiWebViewelse{
            NSLog(@"Unknown address %@",host);
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}
Copy the code

2. Use MessageHandle

WKUserContentController *userContentController = [[WKUserContentController alloc] init]; [configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] Name: @ "jsFun"];Copy the code

Here messageHandle strongly references self, so the loop reference needs to be broken in viewWillDisAppear

[webView.configuration.userContentController removeScriptMessageHandlerForName:@"jsFun"];
Copy the code

There are also some excellent third-party oc and js interaction frameworks at the end of the article, such as WebViewJavascriptBridge. It is very convenient to use, but it can only be used with front-end development. If you are interested, you can go to know about it. WebViewJavaScriptBridge is basically used