티스토리 뷰

WKWebView에 오면서 javascript level에서 웹뷰와 네이티브의 통신을 이제는 기존처럼 하지 않아도 됩니다.

 

물론 JavascriptCore를 이용하면 안드로이드와 동등한 정도의 script 호출이 가능해 집니다.

 

이건 이전에 제가 적은 글 http://mrgamza.tistory.com/425

 

[iOS/swift] JavaScript를 JavaScriptCore를 사용하기

이전까지 우리는 JavaScript에서 호출되는 function들을 사용하기 위해서 shouldStartLoadWithRequest에서 스키마로 값을 비교하여 모든것을 처리하여 주었다. 이러한 모습은 웹개발시에도 소스가 분리되는 안좋은..

mrgamza.tistory.com

 

자 그럼 내용이 많지 않으니 금방 적도록 하겠습니다.

 

Web → Native 로 호출되는 부분이 주요한 부분일것 같습니다.

 

참고로 JavascriptCore처럼 Web에서 Native의 function을 안드로이드처럼 일반적이게 사용하는 function처럼 호출하는 방법을 아직 찾지는 못하였습니다.

 

예제는 getMessage라는 text를 전달하면, javascript의 message function호출하여서 return 하는 방식입니다.

 

* 이것말고 var message = ' ' 이렇게 전달을 하였더니 가기는 하는데, 첫번째 호출시에는 얼랏이 노출되지 않는 치명적인 문제가 있으니 알아두시기 바랍니다.

 

1. viewDidLoad

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
override func viewDidLoad() {
    super.viewDidLoad()
    
    let contentController = WKUserContentController()
    contentController.add(self, name: "test")
    
    let userScript = WKUserScript(source: "initNative()", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
    contentController.addUserScript(userScript)
    
    let configuration = WKWebViewConfiguration()
    configuration.userContentController = contentController
    
    webView = WKWebView(frame: view.frame, configuration: configuration)
    webView.uiDelegate = self
    view.addSubview(webView)
    
    let localFile = Bundle.main.path(forResource: "test", ofType: "html") ?? "" // 반드시 존재하므로 그냥 처리
    let url = URL(fileURLWithPath: localFile)
    let request = URLRequest(url: url)
    webView.load(request)
}
cs

 

파일은 로컬로 저장된 파일을 사용하였고, 

특이한 부분은 contentController에 test를 넣어주었는데요. 이것이 javascript에서 호출하는 이름이 됩니다.

initNative()는 웹페이지가 다 불리고 난 이후에 호출되므로 webView에서 초기화를 여기에서 시켜주면 됩니다.

 

2. WKScriptMessageHandler 구현하기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
extension ViewController: WKScriptMessageHandler {
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "test" {
            if let dictionary: [StringString= message.body as? Dictionary {
                if let action = dictionary["action"] {
                    if action == "bind"let name = dictionary["name"] {
                        if name == "message" {
                            let dateString = Date().description
                            webView.evaluateJavaScript("var \(name) = '\(dateString)';", completionHandler: nil)
                        }
                    } else if action == "call"let function = dictionary["function"] {
                        var returnMessage = ""
                        if function == "returnFunction" {
                            returnMessage = "나는 선택받은 function이다."
                        }
                        
                        webView.evaluateJavaScript("\(function)('\(returnMessage)')", completionHandler: nil)
                    }
                }
            } else if let message = message.body asString {
                if message == "getMessage" {
                    webView.evaluateJavaScript("returnMessage('나는 function에 호출된 녀석입니다.');", completionHandler: nil)
                }
            }
        }
    }
}
cs

 

뭐 간단한 소스 입니다. json 형식으로 들어오게 되면 Dictionary로 변환해서 들어온 action에 따라서 하여야 하는 행동을 하는것입니다.

코드중에 evaluateJavaScript가 있는데, 이 부분을 이용하여서 webpage의 javascript를 호출 가능합니다. 여기에서는 구현을 하지는 않았지만 completionHandler에서 return값을 가져와서 사용도 가능하니 그 부분은 만들어 보도록 하죠. 너무 쉬우니까요. 모르겠으면 댓글을 ㅠㅠ

 

3. 웹 구현

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!DOCTYPE html>
<html>
<head>
    <title>JavaScript Test</title>
    <style type="text/css">
        #container {
            margin-top: 30pt;
        }
        button {
            background-color: gray;
            border: none;
            padding: 10pt;
            font-size: 20pt;
            width: 100%;
        }
    </style>
    <script type="text/javascript">
        function initNative() {
            bind()
        }
        
        function bind() {
            var message = {
                'action''bind',
                'name''message'
            };
            window.webkit.messageHandlers.test.postMessage(message);
        }
    
        function test() {
            alert('(Web)test()\nmessage :\n' + message);
        }
    
        function getMessage() {
            window.webkit.messageHandlers.test.postMessage('getMessage');
        }
    
        function returnMessage(text) {
            alert('(Native)returnMessage() :\n' + text);
        }
    
        function callFunction() {
            var message = {
                'action''call',
                'function''returnFunction'
            };
            window.webkit.messageHandlers.test.postMessage(message);
        }
    
        function returnFunction(text) {
            alert('(Web)returnFunction() :\n' + text);
        }
    </script>
</head>
<body>
    <div id='container' align='center'>
        <button onclick='bind();'>Call bind()</button></br>
        <button onclick='test();' style='margin-top: 10px'>Print Binding Data</button></br>
        <button onclick='getMessage();' style='margin-top: 10px'>Call getMessage()</button></br>
        <button onclick='callFunction();' style='margin-top: 10px'>Call callFunction()</button></br>
    </div>
</body>
</html>
 
cs

 

정말 별거 없이 받아오고 넘겨주고 하고 있습니다.

 

소스는 github에 올려두었습니다.

 

https://github.com/outofcode-example/iOS-WKWebView

 

outofcode-example/iOS-WKWebView

Contribute to outofcode-example/iOS-WKWebView development by creating an account on GitHub.

github.com

2020.05.28. 추가 - 관련하여서 cocoapod lib 도 만들었습니다.

2020/05/24 - [My] - JSFuction

 

JSFuction

요즘 애플에서 WKWebView를 사용하도록 하면서 javascript를 사용하는 방법들을 문의 하시는 분들이 조금 있어서. 안드로이드처럼 조금 쉽게 사용하는 방법을 개발하였습니다. https://github.com/outofcoding

mrgamza.tistory.com

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함