【Swift】PresentedViewControllerからRootViewControllerを変更するとメモリリークする件

モーダルのようにPresentしたViewControllerからRootViewControllerを変更した際に、メモリリークしていたのでリークしない方法を調べました。

1. 問題の再現

1-1. 構成

構成図は以下のようになっています。

 

  1. PresentingViewController(最初のRootViewController)
  2. PresentedViewController(モーダルのようにPresentされるViewController)
  3. TopViewController(変更先のRootViewController)

 

1-2. 流れ

流れは以下です。

 

 

それぞれのコードは以下です。

 

 

 

 

 

 

 

アプリがクラッシュする訳ではないので、一見問題ないように見えますが、Debug View Hierarchyを見てみましょう。

 

 

 

RootViewControllerをTopViewControllerに変更してもなお裏にUITransitionViewが残っており、中にはPresentedViewControllerが入っています。

 

 

このUITransitionViewは明示的に取り除かない限り、ずっと残り続けるので常にメモリリークしている状態になります。

 

 

原因となる部分は調べても見つかりませんでした;;

RootViewControllerを変更する際に内部でUIWindowを強参照してるんでしょうか?

2. UIWindowを変更する

RootViewControllerのみを変更するとメモリリークしてしまうので、UIWindowごと取り替えてしまいます。

 

 

UIWindowのsubviewを全て取り除く方法もありますが、あまり良くないらしいので上記の方法にしました。

 

 

AppDelegateのchangeRootViewController()を以下のように変更します。

 

 

もう一度changeRootViewControllerを呼び出し、Debug View Hierarchyを見てみましょう。

 

 

 

 

UIWindowの中はrootViewControllerのTopViewControllerだけになりました。

ちなみにpresentViewControllerしてなければ普通にrootViewControllerを替えるだけで問題ありません。

参考URL