뷰 위에 오프라인으로 저장된 HTML 페이지를 표시하는 예제입니다.

1) WebKit View를 뷰 위에 추가합니다.

 

2) 뷰 컨트롤러 소스 파일에 웹킷 뷰를 연결한 @IBOutlet 변수를 추가합니다.

 

3) 다음 프로젝트 폴더에서 마우스 오른쪽 버튼을 누른 뒤 Show in Finder 메뉴를 선택해 파인더 탐색기를 엽니다.

 

4) 웹페이지 파일을 담을 새로운 폴더를 생성합니다.

 

5) 다음 이 폴더를 프로젝트 내부로 드래그합니다.

 

6) 그러면 다음 창이 뜨는데 여기서 Create folder references를 선택합니다. 이 옵션을 선택해야 이미지 파일 등의 static 파일을 표시할 수 있습니다.

 

7) 완료하였다면 다음과 같은 파란색 폴더 모양의 폴더 레퍼런스가 생성되었습니다.

 

8) 위 폴더에 index.html 파일과 이미지 파일등을 생성한 뒤, 페이지를 작성합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    h1 {
      background-color: antiquewhite;
    }
  </style>
</head>
<body>
  <h1>안녕하세요</h1>
  <img src="image.png" width="100%">
  <a href="https://google.com">하이퍼링크</a>
  <button id="btn-alert">자바스크립트</button>
</body>
</html>

image.png 파일은 index.html 파일과 동일한 위치에 있으면 표시됩니다. 앞서 폴더 옵션에서 groups를 선택했었다면 경로를 알 수 없게 되어 이미지 파일을 지정할 수 없습니다.

 

9) 뷰 컨트롤러에서 해당 뷰 컨트롤러에 대한 extension 코드를 작성합니다.

import WebKit
extension ViewController: WKUIDelegate, WKNavigationDelegate {
    func loadHelpPage() {
        // 웹 파일 로딩
        webView.uiDelegate = self
        webView.navigationDelegate = self

        let pageName = "index"
        guard let url = Bundle.main.url(forResource: pageName, withExtension: "html", subdirectory: "webpage") else {
            return
        }
        webView.loadFileURL(url, allowingReadAccessTo: url)
    }
}
  • WKUIDelegateWKNavigationDelegate 프로토콜을 구현하고, 해당 웹킷뷰의 딜리게이트와 뷰 컨트롤러 클래스를 연결합니다.
  • subdirectory에 폴더 이름을 지정하고, 파일 이름(forResource)과 확장자(withExtension)를 입력합니다..
  • loadFileURL은 로컬 웹 페이지를 읽어옵니다. URL을 기입합니다. allowingReadAccessTo 부분은 동일한 URL을 지정하면 해당 파일만 접근할 수 있고, 다른 디렉토리를 지정하면 해당 디렉토리 내에 있는 파일에 접근할 수 있는 권한을 가지게 됩니다.

 

viewDidLoad() 등에서 위 함수를 실행합니다.

override func viewDidLoad() {
    super.viewDidLoad()

    loadHelpPage()
}

 

시뮬레이터를 실행하면 다음과 같이 웹 페이지가 열리게 됩니다.

HTML과 CSS를 적용할 수 있습니다. 자바스크립트가 동작하려면 별도 허용 절차가 필요하며 꽤 복잡하기 때문에 여기서는 다루지 않겠습니다.

 

추가 사항으로, 로컬 웹페이지에서 외부 링크는 해당 웹킷뷰 내에 표시하는 것보다 외부 브라우저에서 표시하는 것이 적당하다고 생각됩니다. 불편하기도 하고 앱스토어 심사 시 외부 웹에 대한 무제한 액세스 허용으로 인식할 수 있기 때문입니다.

하지만 링크 태그에 target="_blank" 등을 적용해도 작동하지 않습니다. 하이퍼링크를 외부 브라우저에서 표시하려면 다음 코드를 추가해야 합니다.

 // 링크 클릭시 외부 사파리 브라우저에서 열리게 하기
 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
     guard case .linkActivated = navigationAction.navigationType,
           let url = navigationAction.request.url
     else {
         decisionHandler(.allow)
         return
     }
     decisionHandler(.cancel)
     UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
  • case 문법은 switch ~ case 문법의 축약형으로 navigationType이 .linkActivated 타입인지 검사하는 부분입니다. 다음과 같이 바꿔쓸 수 있습니다.
    • guard navigationAction.navigationType == .linkActivated, let url = navigationAction.request.url
  • url 변수가 생성되었다면 UIApplication.shared.open을 통해 해당 URL을 외부 브라우저에서 열도록 변경합니다.