teunteun2
JavaScript 웹뷰 -> iOS WKWebView 통신 본문
우선 앱에서 웹뷰를 띄워야하면 SFSafariViewController 혹은 WKWebView를 사용한다
웹앱 통신에 대해 알아보기 전에 간단히 왜 웹인터페이스와의 상호작용을 구현할 땐 WKWebView를 사용하는지 부터 , ..
SFSafariViewController
SFSafariViewController 는 띄우고자 하는 웹 url을 사파리 뷰로 띄우는 것이기 때문에,
웹뷰 커스텀이 필요없거나 , 웹 컨텐츠와의 상호작용 없이 그저 웹뷰를 띄우기만 할 때 자주 쓰인다.
그리고 사파리 인터페이스를 앱에서 그대로 띄우는 것이라서 유저가 사파리 기능을 사용할 수 있다.
하지만 유저가 SFSafariViewController를 통해 어떤 사파리 기능 (자동완성 데이터, 검색 기록, 웹사이트 데이터)을 사용했는지는 알 수 없다 (접근 못함)
웹 인터페이스를 제어하고 싶거나, 웹과 상호작용을 하고 싶다면 WKWebView 를 사용하라고
SFSafariViewController 공식문서에 기재되어 있다.
https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller
WKWebView
아 사파리뷰다 ! 라고 바로 인식할 수 있는 SFSafariViewController에 반해
앱 UI와 별 차이를 못느끼게끔 웹뷰를 띄울 수 있는 WKWebView
웹뷰가 앱 레이아웃을 더 잘 충족시킬 수 있을 때 사용한다 (ㅋㅋ)
(혹은 앱 업데이트 없이 웹뷰 콘텐츠만 바꿔 자주 업데이트를 하고싶을 때)
또 delegate 객체를 통해 navigation이나 사용자 경험을 제어할 수 있다
(ex1. 사용자가 웹 콘텐츠에서 링크를 클릭했을 때 navigation delegate를 통해 특정 조건 불충족 시 네비게이션 못하도록 막을 수 있음)
(ex2. UI delegate를 사용해서 웹과의 상호작용데 대한 응답으로 UI 요소를 표시할 수 있음)
https://developer.apple.com/documentation/webkit/wkwebview
웹(JavaScript로 구현된) -> 앱(iOS)
웹에서 발생된 메세지를 앱에서 받는 기능을 구현해야 했다.
그냥 이렇게 저렇게 하면 된다고 쓰려다가 WKUserContentController랑 WKScriptMessageHandler가 무엇인지 위주로 정리해보았다.
WKScriptMessageHandler
웹페이지의 JavaScript 코드로부터 메세지를 받을 수 있는 인터페이스
https://developer.apple.com/documentation/webkit/wkscriptmessagehandler
자바스크립트로 구현된 웹뷰로부터 메세지를 받아야할 때 WKScriptMessageHandler 프로토콜을 채택한다
1. JavaScript 코드에서 앱(iOS)에서 설정한 <messageHandlerName> (ex. dismiss) 을 대상으로 하는 메세지를 보낸다
window.webkit.messageHandlers.<messageHandlerName>.postMessage(<messageBody>)
2. WebKit이 WKScriptMessageHandler 프로토콜의 userContentController(_: didReceive:) 메서드를 호출한다
3. userContentController(_: didReceive:) 내부에서 받은 메세지를 핸들링한다
extension WKWebViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "dismiss" {
// 핸들링
}
}
}
어떤 메세지를 받았는지 <messageHandlerName>, 그리고 해당 핸들러가 어떤 바디를 가지고 왔는지 <messageBody> 를 확인하려면 각각 message.name , message.body 에 접근
근데 생각해보면 메세지핸들러 이름을 앱과 프론트 두군데에서 '이 이벤트의 이름은 <messageHandlerName> 이라고 하자!' 라고 해준 적이 없다. 위 내용만 읽어보면 일방적으로 프론트에서 <messageHandlerName> 라는 이름으로 메세지를 보내고 있을 뿐 ,..
WKUserContentContrller를 통해 메세지 핸들러 이름을 만들어주어야 한다
WKUserContentController
JavaScript 코드와 웹 간의 상호작용을 관리하고 웹뷰의 내용을 필터링하기 위한 객체
-> WKUserContentController 객체는 웹뷰에서 실행되는 자바스크립트 코드와 앱(iOS) 사이의 'bridge'를 제공하며 다음과 같은 작업을 수행한다
- 웹뷰의 웹페이지에 자바스크립트 코드를 주입한다
- 앱의 네이티브 코드로 호출할 수 있는 커스텀 자바스크립트 함수를 만든다 (install... 이라고 되어있는데 만든다고 기재)
- 웹페이지가 제한된 컨텐츠를 불러오지 못하도록 필터링 한다
WKUserContentConroller은
WKWebView의 configuration인 WKWebViewConfiguration 객체의 userContentController 속성에 할당하는 객체이다
let contentController = WKUserContentController()
contentController.add(self, name: "dismiss")
// javascript쪽에서 보내주어야 하는 메세지 핸들러 이름을 add 해준다
let configuration = WKWebViewConfiguration()
configuration.userContentController = contentController
// WKUserContentController은 WKWebViewConfiguration의 userContentController 속성
webView = WKWebView(frame: view.frame, configuration: configuration)
'iOS' 카테고리의 다른 글
WWDC24 링크 정리 (0) | 2024.07.03 |
---|---|
WWDC24 - Platforms State of the Union ~.~ (0) | 2024.06.22 |
WWDC23 - Explore SwiftUI Animation (0) | 2023.08.03 |
[Combine] Processing Published Elements with Subscribers - developer 문서로 시작한 Combine 공부(4) (0) | 2023.06.27 |
[Combine] Controlling Publishing with Connectable Publishers - developer 문서로 시작한 Combine 공부(3) (0) | 2023.06.26 |