iOS에서 WKWebView 붙이는 방법

|

프로젝트내에 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를 변경하는 예제

전체 코드를 우선 보자.

작동 순서는 아래와 같다.

  1. 웹페이지 로딩을 한다
  2. 로딩이 끝나면 자바스크립트 파일내의 mobileHeader()를 실행한다
  3. mobileHeader()는 웹페이지내의 h1 태그를 보고 내용을 변경한다
  4. 변경된 웹페이지를 갱신해준다.
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을 실행한 하면 다음과 같은 화면이 나온다.

webview_jsToiOS_WebScreen

먼저 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()의 화살표를 따라가보자.

webview_jsToiOS

이상.

Comments