25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RxSwiftでUITableViewAlertForLayoutOutsideViewHierarchyのWARNINGが出る問題

Last updated at Posted at 2019-09-30

背景

MacのOSやXcodeのバージョン上げた後にアプリをビルドすると唐突に以下のような警告が出るようになりました。

Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: ...

なんとなくではありますが「ビューの階層(ウィンドウ)にまだテーブルビューが追加されていないけど、セルやヘッダーのレイアウトの指示がされた。バグの原因や無駄なオーバーヘッドにもなる可能性がある。シンボリックブレーキングポイントを使って原因を探ってくれ」的なことが言いたいんだと思います。

環境

  • macOS Mojave 10.14.6
  • Xcode 11.0
  • RxSwift 5.0.1

原因

よくRxSwiftでUITableViewを使う際(適当ではありますが)以下のような実装をしてる方が多いかと思います。

class TestViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    private let disposeBag: DisposeBag = DisposeBag()
    private let stream: Observable<[Int]> = Observable.just([1])

    override func viewDidLoad() {
        super.viewDidLoad()

        stream.asDriver()
            .drive(tableView.rx.items(cellIdentifier: "cell", cellType: SomeCell.self)) { row, element, cell in
                cell.configure(element: element)
            }
            .disposed(by: disposeBag)
    }
}

このよくある実装自体が背景で述べたような警告につながるみたいです。しかし、このままでは何がなんだか分からないので、警告文にあるように「Symbolic Breakpoint」で追求していきます。

Symbolic Breakpointちゃれんじ

以前使ったことがあるような気もするのですが、やり方を一切覚えていなかったのでググりました。今回は備忘録として残しておきたいと思います。まず最初にXcodeの左のウィンドウで右から2番目のタブを選択し、左下にある+ボタンから「Symbolic Breakpoint...」を選びます。

Screen Shot 2019-09-30 at 18.13.12.png

すると、以下のようなウィンドウが表示されるので、言われた通りシンボル欄にUITableViewAlertForLayoutOutsideViewHierarchyを入力します。

Screen Shot 2019-09-30 at 18.14.19.png

エンターを押すと以下のような状態になると思います。これで準備完了です。

Screen Shot 2019-09-30 at 18.10.44.png

実際に動かしてみる

警告が出てた画面を見ると早速停止してくれました。以下のようにObservableType.subscribeProxyDataSource内のobject.layoutIfNeeded()が原因だったようです。

スレッド
Screen Shot 2019-09-30 at 18.25.45.png

コード
Screen Shot 2019-09-30 at 18.28.40.png

さてどうする?

結論から言いますと、しばらく待つのが良いのではないかと思います。というのも、すでに公式でissueとして認識されていますし、PRも作成されています。

一応、タイミング的にはviewWillAppear()以降でバインドすると警告が消えるのでviewDidLoad()に書いてたコードをviewWillAppear()viewDidAppear()に移植することで解決はします。が・・・そもそもviewWillAppear()viewDidAppear()は複数回呼び出されるということもあってviewDidLoad()に書いていたのであまり得策とは言えません。もちろんtake(1)Bool型のフラグを用いて工夫することで一度しか呼び出されないような実装もできるでしょうが、すでに公式も動いているので待つ方が良いのではないでしょうか。

25
11
0

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
  3. You can use dark theme
What you can do with signing up
25
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?