-
Swift WKWebview 구현하기🧑💻/Swift 2023. 8. 5. 19:32반응형
앱에 WebView를 띄워 postMessage를 전달하고 결과를 받아 봅시다.
WKWebview 생성하기
먼저 WebKit을 import 하고 WKWebView 타입 변수를 생성하고 View에 WKWebView를 추가합니다.
import UIKit import WebKit class WebViewController: UIViewController, WKUIDelegate { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() createWebView() } /// WKWebView 생성 func createWebView() { let webConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self webView.frame = view.bounds view.addSubview(webView) } }
WKUIDelegate를 채택하여 WebView의 생성/삭제, JavaScript의 이벤트 수신할 수 있습니다.
https://developer.apple.com/documentation/webkit/wkuidelegateWKWebview 불러오기
WKWebView의 load API를 호출하면 웹페이지를 불러옵니다.
/// WebView 불러오기 func loadWebView() { guard let url = URL(string: "https://주소를 입력하세요") else { return } let request = URLRequest(url: url) webView.load(request) }
PostMessage 보내기
window.postMessage()와 동일한 역할을 하는 API 이름을 알기 쉽지 않았는데
구글링도 아니고 삽질을 통해 알아냈습니다..ㅎㅎ
WKUserScript를 생성하여 Configuration에 추가해 줍니다./// WKWebView 생성 func createWebView() { let webConfiguration = WKWebViewConfiguration() //////////////////////////////////// // postMessage 설정 let requestData: String = "전송할 데이터" let userScript = WKUserScript(source: "postMessage('\(requestData)')", injectionTime: .atDocumentEnd, forMainFrameOnly: true) webConfiguration.userContentController.addUserScript(userScript) webConfiguration.preferences.javaScriptEnabled = true //////////////////////////////////// webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self view.addSubview(webView) }
메시지 수신하기
메시지를 수신하기 위해 WKScriptMessageHandler를 채택하고, userContentController에 응답이름을 등록합니다.
WKScriptMessageHandler는 userContentController(_:didReceive:) 함수를 필수로 구현해야 합니다.
message.body로 수신한 메시지를 확인해 봅시다.class WebViewController: UIViewController, WKUIDelegate, WKScriptMessageHandler { var webView: WKWebView! let responseName: String = "응답이름" override func viewDidLoad() { super.viewDidLoad() createWebView() } /// WKWebView 생성 func createWebView() { let webConfiguration = WKWebViewConfiguration() // postMessage 설정 let requestData: String = "전송할 데이터" let userScript = WKUserScript(source: "postMessage('\(requestData)')", injectionTime: .atDocumentEnd, forMainFrameOnly: true) webConfiguration.userContentController.addUserScript(userScript) webConfiguration.preferences.javaScriptEnabled = true //////////////////////////////////// // 메시지 수신할 핸들러 등록 webConfiguration.userContentController.add(self, name: responseName) //////////////////////////////////// webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self view.addSubview(webView) } /// WebView 메시지 핸들러 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard message.name == responseName, let body = message.body as? String else { return } // body를 파싱하거나 결과 메시지를 확인합니다. NSLog("수신한 메시지: \(body)") } }
WebView에서 카메라 사용 시 카메라 권한 확인하기
Configuration에 allowsInlineMediaPlayback을 true로 설정합니다.
카메라 권한이 있을 경우 이전에 구현한 loadWebView를 호출하도록 했습니다.
그런데 카메라 권한을 앱에서 줘도 WebView에서 한 번 더 체크하더라구요? 제거하는 방법은 찾지 못했습니다.. 어쩔 수 없는 것인지..import AVFoundation /// WKWebView 생성 func createWebView() { let webConfiguration = WKWebViewConfiguration() //////////////////////////////////// // 카메라 권한 허용 webConfiguration.allowsInlineMediaPlayback = true //////////////////////////////////// // postMessage 설정 let requestData: String = "전송할 데이터" let userScript = WKUserScript(source: "postMessage('\(requestData)')", injectionTime: .atDocumentEnd, forMainFrameOnly: true) webConfiguration.userContentController.addUserScript(userScript) webConfiguration.preferences.javaScriptEnabled = true // 메시지 수신할 핸들러 등록 webConfiguration.userContentController.add(self, name: responseName) webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self view.addSubview(webView) } /// Camera 권한 체크 func checkCameraPermission() { let permission = AVCaptureDevice.authorizationStatus(for: .video) switch permission { case .authorized: DispatchQueue.main.async { self.loadWebView() } case .denied: let alert = UIAlertController(title: "카메라 권한 필요", message: "설정 > 개인 정보 보호 > 카메라에서 권한을 변경하실 수 있습니다.", preferredStyle: .alert) let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) alert.addAction(okAction) present(alert, animated: false, completion: nil) return case .notDetermined: // 권한 요청 AVCaptureDevice.requestAccess(for: .video) { granted in if granted { DispatchQueue.main.async { self.loadWebView() } } else { NSLog("권한이 거부되었습니다.") } } default: NSLog("Permission = \(permission.rawValue)") } }
카메라 권한을 얻기 위해서는 Info.plist에 Privacy - Camera Usage Description을 설정해야 합니다.
안할 경우 crash 발생합니다.JSON Encoding/Decoding
/// JSON Encoding func encodedString() -> String? { var jsonData: [String: Any] = [] do { // JSON let jsonData = try JSONSerialization.data(withJSONObject: jsonData, options: .prettyPrinted) return encodedString = String(data: jsonData, encoding: .utf8) } catch { NSLog(error.localizedDescription) } return nil } /// JSON Decoding func parsingJson(_ jsonString: String) -> MyResponse? { if let jsonData = jsonString.data(using: .utf8) { let decoder = JSONDecoder() let response = try? decoder.decode(MyResponse.self, from: jsonData) return response } return nil } struct MyResponse: Codable { let result: String }
반응형