【SwiftUI】iOS15でUIKitを使うとメモリ排他アクセスでクラッシュする

SwiftUI

iOS15にアップデートした端末でテストしていると、
iOS14では問題なかった箇所でクラッシュしていました。

UIViewControllerRepresentableで使用しているViewControllerで
viewDidLoad内でaddSubviewしたタイミングでメモリ排他アクセスが出来ておらずクラッシュします。

エラーメッセージは以下の通りです。

Simultaneous accesses to 〜, but modification requires exclusive access error

問題箇所

実際のコードでは分かりにくいので省略・改変しています。
このコードで起きるかは分からないのでご注意ください。

struct WrapperView: UIViewControllerRepresentable {
    typealias UIViewControllerType = WrapperView

    func makeUIViewController(context: Context) -> UIViewControllerType {
        let vc = ViewController()
     //初期化処理(略)
        return vc
    }

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        //更新処理(略)
    }
}

class ViewController:UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
     let webView = WKWebView()
        webView.translatesAutoresizingMaskIntoConstraints = false

        //ここのaddSubviewで落ちる
        self.view.addSubview(self.tabWebObj)

        webView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
        webView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
        webView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        webView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }
}

SwiftUIが描画を行う際にviewDidLoadを呼び出した時、
複数回呼ばれてクラッシュしていました。

どうやら画面を再構成する際に並行して同じViewControllerのviewDidLoadが走っている様です。

解決策

メモリに同時アクセスしているのが問題なので同一スレッドで処理させます。
描画関係の処理なのでDispatchQueue.mainに投げてしまいます。

class ViewController:UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
     let webView = WKWebView()
        webView.translatesAutoresizingMaskIntoConstraints = false

        DispatchQueue.main.async {
            self.view.addSubview(self.tabWebObj)

            webView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
            webView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
            webView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            webView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        }
    }
}

あまり気持ちの良い解決策ではありませんが、
iOS15からである事と、アプリがクラッシュする為、
暫定的にこの対応をしました。

コメント

タイトルとURLをコピーしました