Things take time

[SWIFT] WKWEBVIEW를 이용한 하이브리드 앱 : 웹 뷰 세팅 본문

iOS (기능)

[SWIFT] WKWEBVIEW를 이용한 하이브리드 앱 : 웹 뷰 세팅

겸손할 겸 2017. 4. 18. 17:26

[웹뷰]


웹 페이지를 보여주는 컴포넌트, 컨트롤이다. 하이브리드 앱의 기본이며, 웹(JavaScript) <-> 네이티브(iOS)의 통신을 바탕으로 웹의 기능과 네이티브의 기능을 모두 사용할 수 있다.

네이티브 호출이나 웹뷰에 대한 세팅을 어느 정도 편리하게 잡아줘서, 개발 시 편리함을 추가하는 중간 프레임워크(폰갭, 코르도바 등)가 있지만 기본 내장 클래스만을 이용하여 직접 구현하고자 한다.


iOS에서는 스토리보드에서 가져다 쓸 수 있는 웹뷰, UIWebView를 상속받는 웹뷰가 있고.. 8버전때부터인가 나온 WKWebView가 있다. 초보자에게는 UIWebView가 간편하고 가져다 쓰기 편하지만, 속도나 기능성면으로는 WKWebView를 추천한다고 한다. 그러므로 이 WKWebView를 이용하여 기본 웹뷰를 세팅한다.


내 기록용으로 작성하기에, 완전히 자세한 설명까지는 없다. 그러나 내가 현재 초보이기 때문에 보기에 무리는 없을 듯


[준비]


1. 프로젝트를 생성한다.

2. 기본 ViewController.swift를 사용해도 되지만, 나는 MainViewController.swift란 파일을 하나 생성하여 스토리보드내 뷰 컨트롤러와 연결시켰다. 이 부분은 선택, 기본 ViewController.swift에서 작성해도 된다.

3. 뷰 컨트롤러 내에 기본 View를 넣는다. 그리고 AutoLayout을 정한다. (화면을 웹뷰로 꽉 채우기 위함) : MapViewController는 무시한다.



4. 이제 코드를 수정할 차례다.

import UIKit
import WebKit

class MainViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {

    @IBOutlet weak var webView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

먼저 WebKit을 import한다, 당연히 WKWebView가 포함된 라이브러리를 의미한다. 그리고 WKWebView 관련 메소드를 사용하기 위한 프로토콜 두 개와 자바스크립트 연동을 위한 프로토콜 하나를 추가한다.


그리고 딜리게이트 = self 및 기타 작업을 수행한다.

딜리게이트.. 흔히 자바의 인터페이스처럼 iOS에는 프로토콜이 있다. 그 프로토콜을 상속받는다면, 프로토콜안에 명시된 함수중 optional 형식이 아닌 함수는 무조건 재정의해야 한다. 자바의 인터페이스에서 abstract로 선언된 함수를 상속받은 클래스에서 무조건 재정의하는 것처럼.. 다만 여기엔 딜리게이트라는 개념이 들어가서, 해당 프로토콜에 var delegate로 선언된 변수가 있는데.. 이 변수는 해당 프로토콜을 상속받은 클래스에서 self로 명시하여 사용할 것이다 라고 알려주는 것이다. 이것이 선언되야 해당 프로콜안에 있는 함수를 재정의하여 사용할 조건이 되는 것이다. 비슷한 개념으로 datasource가 있다.


어쨌든, 그래서 나타난 코드는!

import UIKit import WebKit class MainViewController: UIViewController, WKUIDelegate, WKNavigationDelegate { var webView: WKWebView! var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView() override func loadView() { super.loadView() webView = WKWebView(frame: self.view.frame) webView.uiDelegate = self webView.navigationDelegate = self self.view = self.webView! } override func viewDidLoad() { super.viewDidLoad() let myBlog = "http://www.naver.com" let url = URL(string: myBlog) let request = URLRequest(url: url!) webView.load(request) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @available(iOS 8.0, *) public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Swift.Void){ let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) let otherAction = UIAlertAction(title: "OK", style: .default, handler: {action in completionHandler()}) alert.addAction(otherAction) self.present(alert, animated: true, completion: nil) } @available(iOS 8.0, *) public func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Swift.Void){ let alert = UIAlertController(title: "", message: message, preferredStyle: .alert) let cancelAction = UIAlertAction(title: "CANCEL", style: .cancel, handler: {(action) in completionHandler(false)}) let okAction = UIAlertAction(title: "OK", style: .default, handler: {(action) in completionHandler(true)}) alert.addAction(cancelAction) alert.addAction(okAction) self.present(alert, animated: true, completion: nil) } @available(iOS 8.0, *) public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!){ activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge) activityIndicator.frame = CGRect(x: view.frame.midX-50, y: view.frame.midY-50, width: 100, height: 100) activityIndicator.color = UIColor.red activityIndicator.hidesWhenStopped = true activityIndicator.startAnimating() self.view.addSubview(activityIndicator) } @available(iOS 8.0, *) public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){ //activityIndicator.stopAnimating() self.activityIndicator.removeFromSuperview() } }

딜리게이트 함수인 webView의 매개변수를 보면 어떨 때 동작하는지 알 수 있다. 또한 웹에서 사용한 alert, confirm함수는 네이티브에서 재정의해 UIAlertController를 이용한 경고창으로 활용한다. 


결과창은 아래처럼



** 참고로 인터넷을 사용하려면 plist에서 인터넷 관련 설정을 해야한다. http통신 관련이므로 꼭 입력한다.




테스트 환경 : Xcode 8.31 / 시뮬레이터 : iOS 10.3