티스토리 뷰
WKWebView에 오면서 javascript level에서 웹뷰와 네이티브의 통신을 이제는 기존처럼 하지 않아도 됩니다.
물론 JavascriptCore를 이용하면 안드로이드와 동등한 정도의 script 호출이 가능해 집니다.
이건 이전에 제가 적은 글 http://mrgamza.tistory.com/425
자 그럼 내용이 많지 않으니 금방 적도록 하겠습니다.
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: [String: String] = 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 as? String {
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
2020.05.28. 추가 - 관련하여서 cocoapod lib 도 만들었습니다.
'Mobile > iOS' 카테고리의 다른 글
deprecated, unavailable 만들기 (0) | 2018.03.23 |
---|---|
RxSwift. Observable과 Driver (0) | 2018.03.03 |
swift. WKWebView의 javascript alert, confirm 사용하기 (6) | 2018.03.01 |
[iOS/swift] View에 View를 넣고 순서 변경하기 (0) | 2018.02.12 |
xcode에서 swift 주석 달기 (0) | 2018.01.24 |
- Total
- Today
- Yesterday
- Linux
- SWIFT
- Java
- php
- CentOS
- ios
- nodejs
- centos8
- rxswift
- Codable
- intellij
- enum
- github
- android
- ubuntu
- windows10
- golang
- Kotlin
- Xcode
- Gradle
- Spring
- docker
- go
- Windows
- tomcat
- war
- git
- MySQL
- Python
- cocoapods
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |