UITabbarControllerにWKWebViewを配置した場合、タブが切り替わってからロードが走りWebViewが表示されるのでロード待ちの時間が発生し、ページが表示されるまにで時間がかかってしまう。
これを改善するために裏側でロードを走らせてロード待ちの時間を短縮し、ページの表示速度を上げることが出来ましたのでご紹介します。
■ポイント
- initでwebViewを読み込んでおく。
XibでViewを用意しておく。(あとでwebviewを追加する用) - initの段階ではWebviewの制約は仮で設定しておく。
- 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)
}