1. 程式人生 > >WKWebView 入坑指南

WKWebView 入坑指南

WKWebView 入坑指南

因專案JS互動需要,同時因為支援的系統開始從iOS 8 之後,所以就打算使用WKWebView替換掉專案中的UIWebView。本篇文章會持續更新在使用過程總碰到的問題。

  1. 坑一:在使用測試環境時,因為有時後臺返回url並不規範,url不包含scheme時如果呼叫[self.webView loadRequest:request],app就會直接閃退,直接提示exc bad access,沒有任何錯誤的堆疊顯示。而在UIWebView中如果未指定scheme則是自動在url前新增file://。在訪問失敗後呼叫webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error

    代理回撥中返回error
    如:訪問url如果為www.baidu.com時,WKWebView會直接閃退。而UIWebView則呼叫訪問失敗的代理。url如果為https://www.baidu.com。兩者則都正常。

  2. 坑二:在控制器直接呼叫 [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"xxx"] 進行JS互動時,造成迴圈引用無法釋放控制器(self).retain Cycle打破迴圈引用的方法有兩種:

    中間代理:建立一箇中間代理物件轉發

    @interface WeakScriptMessageDelegate
    : NSObject<WKScriptMessageHandler>
    @property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate; - (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate; @end @implementation WeakScriptMessageDelegate - (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate { self
    = [super init]; if (self) { _scriptDelegate = scriptDelegate; } return self; } - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message]; } @end
    使用時:
    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    [userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"xxx"];
    

    手動釋放,在檢視控制器Appear時新增,Disappear時移除。

    
    - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    WKUserContentController *controller = self.webView.configuration.userContentController;
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"xxx"];
    
    }
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        WKUserContentController *controller = self.webView.configuration.userContentController;
        [controller  removeScriptMessageHandlerForName:@"xxx"];
    }