iOS
WebKit
Swift
iOS12

iOS 9~12 で WKWebView 初期化直後の参照カウント数について調べた

以前の記事:

https://qiita.com/srea/items/0d935b0bad4509ddbc50

iOS 11 では、内部の何らかの仕様変更により強参照される仕様に変わっていました。

この記事は続編で iOS 12 ではそのへんの仕様はどうなっているのかを確認しました。


WKWebView と UIView を初期化して weak プロパティに代入してみる


検証コード

import UIKit

import WebKit

final class ViewController: UIViewController {

weak var wkWebView: WKWebView!
weak var uiView: UIView!

override func viewDidLoad() {
super.viewDidLoad()
wkWebView = WKWebView()
print("WebView: \(CFGetRetainCount(wkWebView))")

uiView = UIView()
print("WebView: \(CFGetRetainCount(uiView))")
}
}

スクリーンショット 2018-09-26 19.32.45.png

「weak プロパティのため、すぐ解放されます」と表示されています。

通常であれば、 weak プロパティに代入し、そのあと Print 関数で参照カウント数を取得しようとすると、すでに解放されているためクラッシュするはずです。

では、OS バージョン毎に動作を確認していきます。

どういう結果になるでしょう。


iOS 9.3

クラッシュしました。正しい動きです。

スクリーンショット 2018-09-26 20.27.29.png

コンソールログ

(lldb) 


iOS 10.3.1

クラッシュしました。正しい動きです。

スクリーンショット 2018-09-26 19.42.32.png

コンソールログ

(lldb) 


iOS 11.4

クラッシュしました。が、WebViewは解放されていないようで、参照カウントが2と表示されています。

スクリーンショット 2018-09-26 19.41.04.png

コンソールログ

WebView: 2

(lldb)


iOS 12.0

クラッシュしました。が、WebViewは解放されていないようで、参照カウントが2と表示されています。

スクリーンショット 2018-09-26 19.37.56.png

コンソールログ

WebView: 2

(lldb)


結果比較表

iOS
12
11
10
9

WKWebView 初期化時の参照カウント
2
2
0
0


WKWebView のデバッグメモリグラフ機能を使ってメモリに展開されたオブジェクトを確認する


検証コード

import UIKit

import WebKit

final class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let webView = WKWebView()
print("WebView: \(CFGetRetainCount(webView))")
}
}


iOS 9.3

WebKit (43)

スクリーンショット 2018-09-26 20.47.12.png


iOS 10.3.1

WebKit (48)

スクリーンショット 2018-09-26 20.56.41.png


iOS 11.4

WebKit (53)

スクリーンショット 2018-09-26 20.51.12.png


iOS 12.0

WebKit (2)

WebKit (55)

スクリーンショット 2018-09-26 20.52.25.png


まとめ


  • 差分から iOS 12 でも内部構成に変更が入っていることがわかる


結論


  • よくわからないが、 iOS 11 から WKWebView は WebKit システム内から強参照されるようになった?

  • 循環参照が発生する訳ではないため、 ViewController のプロパティで強参照して問題は無い。


完全に余談

iOS 12 で JSで通信出来ない evaluateJavascript 現象を確認しています。

条件としては、

- 実機 ( Simulator は動く)

- WKWebView を JS の実行のためだけに使っている

- WKWebView をどこにも AddSubview していない又は、AddSubView していても、そのViewController はインスタンス保持のみで表示に使われていない

この場合、 WKWebView を frame zero で AddSubview することで動くようになりました。

Original