[iOS/Swift] Web View Controller

zongbeen·2025년 3월 14일

iOS

목록 보기
6/6
post-thumbnail

Apple Developer

Apple Developr | WKWebView

Overview

  • 웹 콘텐츠를 앱의 UI에 원활하게 통합하는 데 사용하는 플랫폼 네이티브 뷰
  • 웹 뷰는 전체 웹 브라우징 환경을 지원하고 앱의 네이티브 뷰와 함께 HTML, CSS 및 JavaScript 콘텐츠를 제공
  • 웹 기술이 네이티브 뷰보다 앱의 레이아웃 및 스타일 요구 사항을 더 쉽게 충족할 때 사용
    • 예를 들어 앱의 콘텐츠가 자주 변경될 때 사용

iOS 8 이전: UIWebView
iOS 8 이후: WKWebView

Web View 생성

  • [Command + Shift + L]을 통해 WebKit View 라이브러리 가져오기
  • 이후 @IBOutlet weak var webView: WKWebView!과 연결
  • 여기서는 @IBOutlet이 아닌 코드로 작성 예정

코드

import UIKit
import WebKit

class WebViewController: UIViewController, WKUIDelegate {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Web View"
        navigationController?.navigationBar.prefersLargeTitles = false
        setWebView()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.prefersLargeTitles = true
    }
    
    //MARK: - webView에 JavaScript 세팅
    private func setWebView() {
        // JavaScript에서 호출할 핸들러 등록
        let contentController = WKUserContentController()
        contentController.add(self, name: "iosListener")
        contentController.add(self, name: "urlListener")
        
        let config = WKWebViewConfiguration()
        config.userContentController = contentController

        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view.addSubview(webView)

        // HTML 파일 로드
        if let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") {
            let url = URL(fileURLWithPath: htmlPath)
            webView.loadFileURL(url, allowingReadAccessTo: url)
        }
    }
}

extension WebViewController: WKScriptMessageHandler, WKNavigationDelegate {
    //MARK: - JavaScript의 alert 처리
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: "JavaScript Alert", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
            completionHandler()
        })
        present(alert, animated: true, completion: nil)
    }
    
    //MARK: - JavaScript에서 메시지 받았을 때 호출
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        let messageName = message.name
        
        if let messageBody = message.body as? String {
            switch messageName {
            // Swift에서 JavaScript 함수 호출
            case "iosListener":
                print("JavaScript에서 받은 메시지: \(messageBody)")
                let jsCode = "showMessageFromSwift('Hello from Swift!')"
                webView.evaluateJavaScript(jsCode) { (result, error) in
                    if let error = error {
                        print("JavaScript 실행 오류: \(error.localizedDescription)")
                    } else {
                        print("JavaScript 실행 성공: \(String(describing: result))")
                    }
                }
            // JavaScript에서 URL을 받아 WebView 이동
            case "urlListener":
                print("JavaScript에서 받은 URL: \(messageBody)")
                
                if let url = URL(string: messageBody) {
                    let request = URLRequest(url: url)
                    webView.load(request)
                }
            default: break
            }
        }
    }
}

주요 구현 내용

  • WebViewController가 UIViewController를 상속하여 WebView 관리
  • WKWebView를 사용해 웹 콘텐츠를 표시
  • HTML 파일 로드 및 JavaScript 실행 및 메시지 핸들링

주요 메서드

웹뷰 및 JavaScript 설정

  1. WKUserContentController 생성 후 JavaScript에서 호출할 수 있는 핸들러 등록
let contentController = WKUserContentController()
contentController.add(self, name: "iosListener")
contentController.add(self, name: "urlListener")
  1. WKWebViewConfiguration을 설정하여 WebView 초기화
let config = WKWebViewConfiguration()
config.userContentController = contentController
  1. WKWebView 생성 및 uiDelegate, navigationDelegate 설정
webView = WKWebView(frame: view.bounds, configuration: config)
webView.uiDelegate = self
webView.navigationDelegate = self
view.addSubview(webView)
  1. index.html 파일을 로드하여 웹뷰에 표시
if let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") {
    let url = URL(fileURLWithPath: htmlPath)
    webView.loadFileURL(url, allowingReadAccessTo: url)
}

주요 포인트

JavaScript와의 소통

WKScriptMessageHandler를 구현하여 JavaScript에서 호출되는 메시지 처리

  1. JavaScript의 alert() 처리
    1) JavaScript의 alert()이 iOS의 UIAlertController를 통해 메시지를 표시
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
    let alert = UIAlertController(title: "JavaScript Alert", message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
        completionHandler()
    })
    present(alert, animated: true, completion: nil)
}
  1. JavaScript에서 메시지 받기
    1) JavaScript에서 "iosListener"로 메시지를 보내면:
    "showMessageFromSwift('Hello from Swift!')"라는 JavaScript 함수를 실행
    2) JavaScript에서"urlListener"로 메시지를 보내면:
    메시지를 URL로 변환하여 해당 웹 페이지를 로드
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    let messageName = message.name
    if let messageBody = message.body as? String {
        switch messageName {
        case "iosListener":
            print("JavaScript에서 받은 메시지: \(messageBody)")
            let jsCode = "showMessageFromSwift('Hello from Swift!')"
            webView.evaluateJavaScript(jsCode) { (result, error) in
                if let error = error {
                    print("JavaScript 실행 오류: \(error.localizedDescription)")
                } else {
                    print("JavaScript 실행 성공: \(String(describing: result))")
                }
            }
        case "urlListener":
            print("JavaScript에서 받은 URL: \(messageBody)")
            if let url = URL(string: messageBody) {
                let request = URLRequest(url: url)
                webView.load(request)
            }
        default: break
        }
    }
}

HTML 코드

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WKWebView JS Test</title>
</head>
<body>
    <h1>WKWebView & JavaScript 통신</h1>
    
    <button onclick="sendMessageToiOS()">iOS로 메시지 보내기</button>

    <hr>

    <!-- 주소 입력 창 및 이동 버튼 추가 -->
    <input type="text" id="urlInput" placeholder="이동할 주소 입력 (예: https://www.apple.com)">
    <button onclick="navigateToURL()">이동</button>

    <script>
        function sendMessageToiOS() {
            if (window.webkit && window.webkit.messageHandlers.iosListener) {
                window.webkit.messageHandlers.iosListener.postMessage("Hello from JavaScript!");
            }
        }

        function showMessageFromSwift(message) {
            alert("Swift에서 보낸 메시지: " + message);
        }
        
        function navigateToURL() {
            let url = document.getElementById("urlInput").value.trim();
            if (url) {
                if (!url.startsWith("http")) {
                    url = "https://" + url;  // URL이 http나 https로 시작하지 않으면 https 추가
                }

                if (window.webkit && window.webkit.messageHandlers.urlListener) {
                    window.webkit.messageHandlers.urlListener.postMessage(url);
                }
            } else {
                alert("URL을 입력하세요.");
            }
        }
    </script>
</body>
</html>

전체코드

WebViewController
https://github.com/zongbeen/AboutiOS/blob/main/AboutiOS/VIew/WebViewController.swift

실행영상

profile
vis ta vie

0개의 댓글