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

以前の記事：
https://qiita.com/srea/items/0d935b0bad4509ddbc50

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

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

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

## 検証コード

```swift
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](https://qiita-image-store.s3.amazonaws.com/0/1901/f9c8bf22-6904-1f5b-cdfc-c8f5979cbcef.png)

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

では、OS バージョン毎に動作を確認していきます。
どういう結果になるでしょう。

## iOS 9.3

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

![スクリーンショット 2018-09-26 20.27.29.png](https://qiita-image-store.s3.amazonaws.com/0/1901/b846f2c0-a102-70ce-f43c-9589653f66a1.png)

コンソールログ

```
(lldb) 
```

## iOS 10.3.1

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

![スクリーンショット 2018-09-26 19.42.32.png](https://qiita-image-store.s3.amazonaws.com/0/1901/88f4d530-7112-1f2c-8fd3-cb1ef8de09ff.png)

コンソールログ

```
(lldb) 
```

## iOS 11.4

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

![スクリーンショット 2018-09-26 19.41.04.png](https://qiita-image-store.s3.amazonaws.com/0/1901/908f3fa3-82ad-f323-344a-1c16cefa3f37.png)

コンソールログ

```
WebView: 2
(lldb) 
```

## iOS 12.0

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

![スクリーンショット 2018-09-26 19.37.56.png](https://qiita-image-store.s3.amazonaws.com/0/1901/faf4e7d6-71cf-aa0b-3416-225f636fcfee.png)

コンソールログ

```
WebView: 2
(lldb) 
```

## 結果比較表

|iOS|12|11|10|9|
|:-:|:-:|:-:|:-:|:-:|
| WKWebView 初期化時の参照カウント| 2|2|0|0|

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

## 検証コード

```swift
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](https://qiita-image-store.s3.amazonaws.com/0/1901/79f22d2f-07b1-69b2-a0f0-780013ba3b9d.png)


## iOS 10.3.1

WebKit (48)

![スクリーンショット 2018-09-26 20.56.41.png](https://qiita-image-store.s3.amazonaws.com/0/1901/a6ea92f5-bdd0-32a6-9309-0662c4c4e3fc.png)


## iOS 11.4

WebKit (53)

![スクリーンショット 2018-09-26 20.51.12.png](https://qiita-image-store.s3.amazonaws.com/0/1901/67b06d49-fb49-da44-fe4b-a6a9738b4324.png)

## iOS 12.0

WebKit (2)
WebKit (55)

![スクリーンショット 2018-09-26 20.52.25.png](https://qiita-image-store.s3.amazonaws.com/0/1901/c1155690-4653-f622-8273-d20288cba493.png)

## まとめ

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

# 結論

- よくわからないが、 iOS 11 から WKWebView は WebKit システム内から強参照されるようになった？
- 循環参照が発生する訳ではないため、 ViewController のプロパティで強参照して問題は無い。



# 完全に余談

iOS 12 で JSで通信出来ない ~~evaluateJavascript~~ 現象を確認しています。
条件としては、
- 実機 ( Simulator は動く)
- WKWebView を JS の実行のためだけに使っている
- WKWebView をどこにも AddSubview していない又は、AddSubView していても、そのViewController はインスタンス保持のみで表示に使われていない

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

[Original](https://tamazawa.net/2018/09/27/ios-912-で-wkwebview-初期化直後の参照カウント数について調べ/)