그래오늘은이거야

swift IOS about blank 백화현상 wkwebview crash dead webview white background suspend 본문

세상 개발/IOS(Swift)

swift IOS about blank 백화현상 wkwebview crash dead webview white background suspend

jinhongstar 2022. 3. 22. 18:07
728x90
반응형

안녕하세요

 

백화현상은 웹뷰 에서 메모리 누수 또는 웹뷰가 crash(고장)이 나면 발생합니다.

해당 현상(백화)가 발생시점에 앱에서 webViewWebContentProcessDidTerminate 이벤트가 발생합니다.

백화현상을 해결하기 위해 아래와 같이 테스트를 진행 하였습니다.

1. webViewWebContentProcessDidTerminate 이벤트 발생 시점에, 웹뷰를 reload
  (참조 : 웹 사이트 stack overflow 에서 정상 기동 될 것이다.) 
 - (실패) 원인 : suspendMode 로 진입하거나, 장시간미사용 백그라운드로 되어있을때 reload 가 정상적으로 동작하지 않음

2. webViewWebContentProcessDidTerminate 이벤트 발생 시점 Flag 값 (isDidTerminateWebView)만 저장 후 Foreground 시점에 웹뷰 reload
 - (실패) 원인 : reload 가 정상적으로 진행되어도 장시간미사용 백그라운드로 백화(about:blank) 상태로 새로고침만 진행됨

3. foreground 일때도 Reload 도 정상적으로 진행되지 않아, 웹뷰(wkwebview)를 인스턴스객체 메모리를 강제 해제 후 새로운 웹뷰(wkwebview)를 생성 하고, 마지막 load 했던, URL을 다시 생성한 웹뷰(wkwebview)에 loadURL 진행.
 - (실패) 원인 : foreground 일때 앱이 명확하게 활성화 되지 않아, 바이오인증서 및 웹 인터페이스 브릿지가 원할하게 동직하지 않음
 
4. 결론 webViewWebContentProcessDidTerminate 이벤트 발생 시점 Flag 값 (isDidTerminateWebView)만 저장 후 applicationDidBecomeActive 시점에 웹뷰(wkwebview)를 인스턴스객체 메모리를 강제 해제 후 새로운 웹뷰(wkwebview)를 생성 하고, 마지막 load 했던, URL을 다시 생성한 웹뷰(wkwebview)에 loadURL 진행.
 - (성공) 원인 : 앱이 활성화 된 상태에서 바이오인증서 및 웹 인터페이스 브릿지가 원할하게 동작 확인

 

//wkwebview 메모리 누수 weak 로 만든 후 delegate 를 발생시킨다.

class JBWebVCLeakAvoider: NSObject, WKScriptMessageHandler {

    weak var delegate: WKScriptMessageHandler?

    init(delegate: WKScriptMessageHandler) {

        self.delegate = delegate

        super.init()

    }

 

//재정의  Strong > weak 로 delegate 로 변환하여 재 호출

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

        self.delegate?.userContentController(userContentController, didReceive: message)

    }

}

 

 

setup ViewDidLoad 에서는

 

  let config = WKWebViewConfiguration()

        //wkwebview self로 direct add 하면 메모리 누수가 발생하여 weak 로 바뀌어 add 한다.

        config.userContentController.add(JBWebVCLeakAvoider(delegate: self), name: WKWebScriptProtocol.callBackHandlerKey)

 

        let thePreferences:WKPreferences = WKPreferences.init();

        thePreferences.javaScriptCanOpenWindowsAutomatically = true // 팝업 창 사용 가능하도록 설정

        thePreferences.javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정

        config.preferences = thePreferences;

 

class 를 만들고

 

// MARK: - WKScriptMessageHandler

extension JBWebViewController : WKScriptMessageHandler {

    //MARK:- HERE!!! JavaScriptInterfaceMapping

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

        if message.name == WKWebScriptProtocol.callBackHandlerKey {

//            print("전달 받은 Bridge : \(String(describing: (((message.body as! String).urlDecode()!) ).toJSON()))")

            JBBank.shared.interfaceBridge.callToClassWithMethod(responseData: ((message.body as! String).urlDecode()!)) //디코딩해서 inferface전달

          

        }

    }

    

 

}

이런식으로 재호출 하여 storng 메모리를 weak 로 count 하여 메모리 누수를 막을 수 있습니다.

 

webview is crash

웹뷰가 죽는 현상 하얀색 바탕에 멈추는 현상이 있습니다.

 

Javascript 가 쫑나거나 image 를 로드하다가 

백그라운드에서 웹뷰가 사망하는 경우입니다.

 

정말 드물게 발생하는 현상입니다.

 

IOS 개발 하면서 처음보는 현상이라

UIWebview는 crash가 나면 앱을 종료 시켜버렸는데

WKWeview는 crash가 나면 wkwebview만 종료되 버립니다.

 

앱이 멈추는 현상을 WKNavigationDelegate 에서 delegate를 catch 잡을 수 있습니다.

https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455639-webviewwebcontentprocessdidtermi

 

Apple Developer Documentation

 

developer.apple.com

 

func webViewWebContentProcessDidTerminate(_ webView: WKWebView){
        print("\(#function)")
        print("Reload");
        webView.reload()
    }

 

참고 하세요

 

 

반응형
Comments