search
LoginSignup
1
Help us understand the problem. What are the problem?

posted at

updated at

Organization

UITabbarControllerのWebViewを先読み(プリロード)して、表示速度を高速化する。

UITabbarControllerにWKWebViewを配置した場合、タブが切り替わってからロードが走りWebViewが表示されるのでロード待ちの時間が発生し、ページが表示されるまにで時間がかかってしまう。

これを改善するために裏側でロードを走らせてロード待ちの時間を短縮し、ページの表示速度を上げることが出来ましたのでご紹介します。

■ポイント

  1. initでwebViewを読み込んでおく。
    XibでViewを用意しておく。(あとでwebviewを追加する用)
  2. initの段階ではWebviewの制約は仮で設定しておく。
  3. viewDidLoadで用意していたXibのViewにWebViewを追加して、正しい制約をかける。

1. initでWebViewを読み込んでおく。

viewDidLoadでページをロードをしているからロード時間が発生していた。
└ initの段階でページのロードを走らせたい。

  • initでwebViewを使いたいのでwebViewだけはXibで作らない。
    (理由:Xibで作ったViewは、viewDidLoadから使えるようになるのでinitでは使えない為)
  • あとでwebViewをaddSubViewする為の箱を用意する。(webViewContainer)
    // webView入れる用の箱を用意する。
    @IBOutlet weak var webViewContainer: UIView!
    @IBOutlet weak var loadingView: UIActivityIndicatorView!
    @IBOutlet weak var errorView: UIView!
    // initでwebViewを使いたいのでXibで作らない。
    private var webView: WKWebView?

    init() {
        super.init(nibName: nil, bundle: nil)
        // イニシャライザでローディングする。
        preloadWebView()
    }

2. initの段階ではWebViewの制約は仮で設定しておく。(viewDidLoadで正しい制約をつける)

    private func preloadWebView() {
        let config = WKWebViewConfiguration()
        config.allowsInlineMediaPlayback = true
        config.mediaTypesRequiringUserActionForPlayback = []
        
        // 仮の制約をかける
        let width = UIScreen.main.bounds.size.width
        let height = UIScreen.main.bounds.size.height
        webView = WKWebView(frame: CGRect(x: 0, y: 0, width: width, height: height), configuration: config)

        loadWebView()
    }

    private func loadWebView() {
        guard let webView = webView else {
            return
        }
        guard let url = URL(string: "https://www.google.com") else {
            return
        }

        let request = URLRequest(
            url: url,
            cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
            timeoutInterval: 10
        )

        webView.navigationDelegate = self
        webView.load(request)
    }

3. viewDidLoadで用意していたXibのViewにWebViewを追加して、正しい制約をかける。

    override func viewDidLoad() {
        super.viewDidLoad()
        createWebView()
    }

    private func createWebView() {
        guard let webView = webView else {
            return
        }
        if !webView.isDescendant(of: webViewContainer) {
            // 用意していたview(webViewContainer)にWebViewをaddSubViewする。
            self.webViewContainer.addSubview(webView)
            webView.translatesAutoresizingMaskIntoConstraints = false

            // 正しい制約をかける。
            let constraints = [
                webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
                webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
                webView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
                webView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor)
            ]
            NSLayoutConstraint.activate(constraints)
        }
    }

■全体のコード

WebViewController.swift
    @IBOutlet weak var webViewContainer: UIView!
    @IBOutlet weak var loadingView: UIActivityIndicatorView!
    @IBOutlet weak var errorView: UIView!
    private var webView: WKWebView?
    
    init(webViewConfig: WebViewConfig) {
        super.init(nibName: nil, bundle: nil)
        preloadWebView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        createWebView()
    }

    private func preloadWebView() {
        let config = WKWebViewConfiguration()
        config.allowsInlineMediaPlayback = true
        config.mediaTypesRequiringUserActionForPlayback = []

        let width = UIScreen.main.bounds.size.width
        let height = UIScreen.main.bounds.size.height
        webView = WKWebView(frame: CGRect(x: 0, y: 0, width: width, height: height), configuration: config)

        loadWebView()
    }

    private func createWebView() {
        guard let webView = webView else {
            return
        }
        if !webView.isDescendant(of: webViewContainer) {
            self.webViewContainer.addSubview(webView)
            webView.translatesAutoresizingMaskIntoConstraints = false

            let constraints = [
                webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
                webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
                webView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
                webView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor)
            ]
            NSLayoutConstraint.activate(constraints)
        }
    }

    private func loadWebView() {
        guard let webView = webView else {
            return
        }
        guard let url = URL(string: "https://www.google.com") else {
            return
        }

        let request = URLRequest(
            url: url,
            cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
            timeoutInterval: 10
        )

        webView.navigationDelegate = self
        webView.load(request)
    }

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?