iOS에서 WKWebView 붙이는 방법
02 Aug 2018 |프로젝트내에 loginPage.html이 있다는 가정하에 다음과 같이 하면 된다.
참고로 import WebKit 를 반드시 해주어야 한다.
//request 만들고
guard let htmlUrl = Bundle.main.url(forResource:"loginPage", withExtension:"html") else { return }
let request = URLRequest(url:htmlUrl)
webview.load(request)
// UI 구성
self.view.addSubview(webview)
webview.layer.borderWidth = 4.0
webview.layer.borderColor = UIColor.red.withAlphaComponent(0.3).cgColor
webview.addToSuper(top: 10, left: 10, bottom: 10, right: 10)
iOS에서 javaScript를 사용해 HTML를 변경하는 예제
전체 코드를 우선 보자.
작동 순서는 아래와 같다.
- 웹페이지 로딩을 한다
 - 로딩이 끝나면 자바스크립트 파일내의 mobileHeader()를 실행한다
 - mobileHeader()는 웹페이지내의 h1 태그를 보고 내용을 변경한다
 - 변경된 웹페이지를 갱신해준다.
 
class JSFromiOSViewController: UIViewController {
    
    var webview:WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        initWebview_with_callJsFunc_modifyHTML()
        loadUrl()
 
    }
    
    func initWebview_with_callJsFunc_modifyHTML(){
     
        //contents 만듬.
        let contentController = WKUserContentController()
        let userScript = WKUserScript(source: "mobileHeader()",
                                      injectionTime: .atDocumentEnd,
                                      forMainFrameOnly: true )
        //mobileHeader()라는 javaScript 함수가 html로딩완료후 호출됨.
        
        contentController.addUserScript(userScript)
        
        //config 만듬
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        //put it all together
        //자바스크립트 함수를 실행시킬 준비를 미리하고, 이를 configuration에 넣고
        //이를 다시 userContentController에 저장해둔후
        //웹뷰를 만든다.
        webview = WKWebView(frame: CGRect.zero , configuration: config )
    }
    
    func loadUrl(){
        
        //request 만들고
        guard let htmlUrl = Bundle.main.url(forResource:"loginPage", withExtension:"html") else { return }
        let request = URLRequest(url:htmlUrl)
        webview.load(request)
        
        // UI 구성
        self.view.addSubview(webview)
        webview.layer.borderWidth = 4.0
        webview.layer.borderColor = UIColor.red.withAlphaComponent(0.3).cgColor
        webview.addToSuper(top: 10, left: 10, bottom: 10, right: 10)
    }
     
}
- initWebview_with_callJsFunc_modifyHTML() 메소드:
 
우선 WKUserContentController를 이용하여 WebView를 로딩하기 전에 JavaScript 메소드 연동을 미리해주어야 한다. WKWebViewConfiguration 의 userContentController` 의 인자로 세팅해준다.
- loadUrl() 메소드:
 
번들로부터 HTML파일의 url을 가져오고 나서  webview.load(request) 를 사용하여 웹뷰를 로딩하는 부분.
JavaScript를 설정하는 부분을 간단히 그려보면 다음과 같다.
ascii. 그림 들어갈 곳.
다음은 필요한 HTML, JS파일이다.
loginPage.html 는 다음과 같다.
<!--여기부터가 웹페이지 구성내용임.-->
<!DOCTYPE html>
<html>
    <head>
        
        <style type="text/css">
            body {
                padding-top: 40px;
            }
        </style>
        <title>WKWebView Demo</title>
        <meta charset="UTF-8">
            </head>
    <body style="background-color: gray;">
        <h1>JS to Webview Sample</h1>
        
        <form class="form-signin" role="form">
            <div class="form-content">
                
                <label for="email" class="form-email">Already an account?</label>
                <br />
                <input type="email" id="email" class="form-control" placeholder="Email" required autofocus />
                <br />
                <input type="password" id="password" class="form-control" placeholder="Password" required>
                    <br />
                    
                    <button class="btn btn-lg btn-primary btn-block" type="button" onClick="sendLoginAction()">
                        Submit
                    </button>
                    </div>
        </form>
        <script type="text/javascript" src="main.js"></script>
    </body>
</html>
main.js의 내용
function sendLoginAction() {
try {
    webkit.messageHandlers.loginAction.postMessage(
                                                   document.getElementById("email").value + " " + document.getElementById("password").value
                                                   );
} catch(err) {
    console.log('The native context does not exist yet');
}
}
function mobileHeader() {
    document.querySelector('h1').innerHTML = "iOS에서 호출된 증거(이 텍스트는 main.js에서 가져옴)";
}
레퍼런스: // ref: https://benoitpasquier.com/ios-webkit-swift-and-javascript/ // ref: https://github.com/popei69/WebkitSample/blob/master/WebkitSample/ViewController.swift
iOS에서 javaScript를 사용해 HTML를 변경하는 예제
전체 코드
import UIKit
import WebKit
// HTML상의 js를 invoke시켜 iOS로 응답을 받아냄.
// 예) 웹상에 입력했던 "로그인아이디", "암호"를 iOS로 전송해줌.
class JSToiOSViewController_simple: UIViewController{
    
    var webview:WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        initWebview_then_callFromJs()
        loadUrl()
    }
    
    func initWebview_then_callFromJs(){
        
        //contents컨트롤러 만듬.
        let contentController = WKUserContentController()
        contentController.add(self, name:"doneAction")
        
        //config 만듬
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        //위 인자사용한 초기화
        webview = WKWebView(frame: CGRect.zero , configuration: config )
    }
    
    func loadUrl(){
        
        //request 만들고
        guard let htmlUrl = Bundle.main.url(forResource:"buttonPress", withExtension:"html") else { return }
        let request = URLRequest(url:htmlUrl)
        webview.load(request)
        
        // UI 구성
        self.view.addSubview(webview)
        webview.layer.borderWidth = 4.0
        webview.layer.borderColor = UIColor.red.withAlphaComponent(0.3).cgColor
        webview.addToSuper(top: 10, left: 10, bottom: 10, right: 10)
    }
    
}
extension JSToiOSViewController_simple:   WKScriptMessageHandler{
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        if message.name == "doneAction" {
            print("JavaScript 에서 메시지가 왔어요 \(message.body)")
        }
    }
    
}
buttonPress.html
<html>
    <head>
        <title>WKWebView Demo</title>
        <meta charset="UTF-8">
    </head>
    
    <body style="background-color: gray;">
        <h1>js함수를 기다림....내용을 적고, 완료버튼을 누르세요</h1>
        <input type="email" id="email" class="form-control" placeholder="Email" required autofocus />
        <br />
        
        <button class="btn btn-lg btn-primary btn-block" type="button" onClick="sendDoneAction()">
            완료
        </button>
        
        <script type="text/javascript" src="main.js"></script>
    </body>
</html>
MAIN.JS
function sendDoneAction() {
    try {
        webkit.messageHandlers.doneAction.postMessage ( document.getElementById("email").value );
    } catch(err) {
        console.log('The native context does not exist yet');
    }
}
일단 App을 실행한 하면 다음과 같은 화면이 나온다.

먼저 HTML파일과 JavaScript 쪽을 보자.
HTML 페이지가 로딩되면 텍스트필드와 버튼이 있다. 여기에 내용을 “하하호호”라고 적고 완료버튼을 누른다.
버튼을 누르면 onClick에 연결된 sendDoneAction() 이 실행된다. 이는 main.js에 있는 메소드이다.
sendDoneAction()내부에는  webkit.messageHandlers.doneAction.postMessage가 있다. 그 코드를 자세히 보면 doneAction이 포함됨을 알 수 있다.
이 doneAction이라는 문자열을 가지고 iOS쪽과 통신을 한다고 보면 된다.
이제 iOS쪽을 보자.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)  델리게이트가 있다.
이곳에서 아래와 같은 코드를 통해 javaScript로 부터 전송된 메시지 내용을 받을 수 있다.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    
    if message.name == "doneAction" {
        print("JavaScript 에서 메시지가 왔어요 \(message.body)")
    }
}
알아야 할 것이 있는데, 위 델리게이트가 정상적으로 동작하기 위해서 WKWebView 설정할 때 아래와 같이 doneAction가 포함된 부분을 명시 해주어야 한다.
//contents컨트롤러 만듬.
let contentController = WKUserContentController()
contentController.add(self, name:"doneAction")
전체 구조
전체 구조를 보면 다음 그림과 같다.
sendDoneAction()의 화살표를 따라가보자.

이상.
             
            Eddie Kwon - Development log for ML, iOS
            
