メインスレッドチェッカー:バックグラウンドスレッドで呼び出されるUI API:-[UIApplication applicationState]


107

Xcode 9ベータ、iOS 11でGoogleマップを使用しています。

次のようにログにエラーが出力されます。

メインスレッドチェッカー:バックグラウンドスレッドで呼び出されるUI API:-[UIApplication applicationState] PID:4442、TID:837820、スレッド名:com.google.Maps.LabelingBehavior、キュー名:com.apple.root.default-qos.overcommit 、QoS:21

コードのメインスレッドからインターフェイス要素を変更していないことがほぼ確実なので、なぜこれが発生するのでしょうか。

 override func viewDidLoad() {

    let locationManager = CLLocationManager()


    locationManager.requestAlwaysAuthorization()


    locationManager.requestWhenInUseAuthorization()

        if CLLocationManager.locationServicesEnabled() {

            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            locationManager.startUpdatingLocation()
        }

      viewMap.delegate = self

     let camera = GMSCameraPosition.camera(withLatitude: 53.7931183329367, longitude: -1.53649874031544, zoom: 17.0)


        viewMap.animate(to: camera)


    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let locValue:CLLocationCoordinate2D = manager.location!.coordinate
        print("locations = \(locValue.latitude) \(locValue.longitude)")
    }

    func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {


    }

    func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {

        if(moving > 1){
            moving = 1
        UIView.animate(withDuration: 0.5, delay: 0, animations: {

            self.topBarConstraint.constant = self.topBarConstraint.constant + (self.topBar.bounds.height / 2)

            self.bottomHalfConstraint.constant = self.bottomHalfConstraint.constant + (self.topBar.bounds.height / 2)

            self.view.layoutIfNeeded()
        }, completion: nil)
    }
         moving = 1
    }


    // Camera change Position this methods will call every time
    func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
        moving = moving + 1
        if(moving == 2){


            UIView.animate(withDuration: 0.5, delay: 0, animations: {


                self.topBarConstraint.constant = self.topBarConstraint.constant - (self.topBar.bounds.height / 2)

                self.bottomHalfConstraint.constant = self.bottomHalfConstraint.constant - (self.topBar.bounds.height / 2)


                self.view.layoutIfNeeded()
            }, completion: nil)
        }
        DispatchQueue.main.async {

            print("Moving: \(moving) Latitude: \(self.viewMap.camera.target.latitude)")
            print("Moving: \(moving)  Longitude: \(self.viewMap.camera.target.longitude)")
        }
    }

1
ではmapView(_:didChange)printステートメントをメインキューにディスパッチしています。まだメインキューに入っていませんか?そうでない場合は、animateコールもメインキューにディスパッチする必要があります。dispatchPrecondition(condition: .onQueue(.main))念のため、これらのUI更新の前にいくつか挿入することをお勧めします。
Rob

「コードのメインスレッドのインターフェイス要素を変更しないことはほぼ間違いありません。」私はあなたが「あらゆるバックグラウンドスレッドから」を意味していたと思います。
Rob

2
あなたの問題ではありません。私はそれが彼らの終わりにあると思います。「com.google.Maps.LabelingBehavior」で停止します。私は同じ問題を抱えています。
TarvoMäesepp

2
こんにちは、そうです、問題はグーグルにあるようです、うまくいけば彼らはすぐに更新されたバージョンをリリースするでしょう
MattBlack

1
@MattBlackこの回答を見てください:stackoverflow.com/a/44392584/5912335
badhanganesh

回答:


53

まず、Googleマップの呼び出しとUIの変更がメインスレッドから呼び出されていることを確認します。

Thread Sanitizer を有効にして、問題のある行を見つけることができます。

次のようにして、メインスレッドに問題のある行を置くことができます。

DispatchQueue.main.async {
    //Do UI Code here. 
    //Call Google maps methods.
}

また、Googleマップの現在のバージョンを更新します。グーグルマップはスレッドチェッカーのためにいくつかの更新を行わなければなりませんでした。

質問:「なぜこれが発生するのですか?」Appleがエッジケースのアサーションを追加したと思います。Googleはそのためにポッドを更新する必要がありました。


1
@thibautnoah、私はそれを「GoogleのAPIと組み合わせてxcode 9ベータ版を使用しているために(問題)が発生している」とは言いませんでしたからですか?または、あなたは私の答えでは解決されない同様のバグに直面しているからですか?
ScottyBlades 2017

7
Xcode 9は、xcode 8が明らかに検出しないいくつかのスレッド化の問題を強調しました(xcodeの設定が原因であるか、別のことが決定されるか)。xcode 8に戻すことは、スレッドの問題を無視することと同じです。それらは依然として存在し、解決されません。したがって、それは解決策ではありません。砂に頭を埋めて、すべてが問題ないふりをしているだけです。問題がフレームワークから発生している場合は、修正できるように問題を送信してください。
ティボーノア2017

Xcode 9は、xcode 8が検出するように提案していないスレッド化の問題を検出します。また、GoogleのAPIと組み合わせたXcode 9がこのバグの原因である可能性があります。このバグは複数のクラッシュのデバッガにあり、xcode 8に切り替えてもクラッシュは発生しません
ScottyBlades

要点は、スレッドチェッカーが原因ではなく症状を示していることです。Xcode 9ベータ版が原因であり、症状伝達者でもあると私は言っています。「xcode 8に切り替えてもクラッシュは起こりません」。XCodeの警告とデバッガーの読み出しによる実際のクラッシュには違いがあります。このエラーは、警告またはクラッシュとして表示される可能性があります。xcode 8に戻すと、クラッシュは完全に解消されます。Xcode9ベータは、正当な理由でベータと呼ばれています。
ScottyBlades 2017

2
はい...私は多くのiOS開発者が何かが症状を示しているからといって、それが原因ではないことが保証されていることを意味するのではないことを理解するのは難しいと思います。また、Appleが間違いを犯した可能性があることを受け入れるのも難しいと思います。
ScottyBlades 2017

156

メインスレッドで実行されないUIコードを見つけるのが難しい場合があります。以下のトリックを使用して、それを見つけて修正できます。

  1. スキームの編集->診断を選択し、メインスレッドチェッカーにチェックを入れます。

    Xcode 11.4.1

    メインスレッドチェッカーの横にある小さな矢印をクリックして、メインスレッドチェッカーブレークポイントを作成します。 ここに画像の説明を入力してください

    以前のXcode

    問題の一時停止にチェックを入れます。 ここに画像の説明を入力してください

  2. この問題を再現するには、iOSアプリケーションを実行します。(Xcodeは最初の問題で一時停止するはずです。) ここに画像の説明を入力してください

  3. UIを変更するコードをラップする DispatchQueue.main.async {} ここに画像の説明を入力してください


4
ありがとう、たぶん30分節約してください。
オレンジ

10
何らかの理由で、Xcode 10.1でそれを行うと、無力でコード行に関連付けることができないコールスタックしか得られません:2018-12-29 19:46:56.500629 + 0100 BedtimePrototype [1553:834478] [レポート]メインスレッドチェッカー:バックグラウンドスレッドで呼び出されるUI API:-[UIApplication applicationState] PID:1553、TID:834478、スレッド名:com.apple.CoreMotion.MotionThread、キュー名:com.apple.root.default-qos。オーバーコミット、QoS:0
Vilmir

1
無力に見えるコールスタックも取得しました。左側でで止まり、"com.apple.CoreMotion.MotionThread(23)"他のすべてのスレッドもチェックします。でThread 1、何か私の注意をキャッチ:それはSVProgressHUD(私が使用進捗ビューライブラリ)です。だから、私はそれSVProgressHUD.show()がターゲットView Controllerのどこかへの呼び出しであることを知っています。次に、各外観をラップするDispatchQueue.main.asyncか、単にコメントアウトして、もう一度テストして、問題のあるものを見つけました。
John Pang

2
また、SVProgressHUD.showをコメントアウトして警告を取り除きました。この呼び出しをDispatchQueue.main.asyncにラップしても、警告は消えませんでした。私はv2.2.5でポッドを使用しています。このスレッドは問題をよりよく理解するのに役立ちます:github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir

1
「問題で一時停止」チェックボックスは、xcode 11.4.1にはありません。編集:メインスレッドチェッカーの横に小さな矢印が見つかりました。クリックするとブレークポイントが追加されます。
ChrisO

47

DispatchQueue.main.async {}メインスレッドで確実に実行されるように、UIを変更するコード行をラップします。それ以外の場合は、UIの変更が許可されていないバックグラウンドスレッドから呼び出している可能性があります。このようなコード行はすべてメインスレッドから実行する必要があります。


4
はい私はすでにそれを使用しましたが、警告はまだあります
MattBlack

@Pang、メインのUIコードではなく、印刷に使用されます。
Dimitrie-Toma Furdui 2017

4
@MattBlackは、UIを変更するすべてのものをラップしようとしますDispatchQueue.main.async {}
Dimitrie-Toma Furdui 2017

@ user6603599-作品の魅力のような
SREE

3

このリンクを参照してください https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

私にとっては、ブロックから呼び出したときにこれが機能しました。


1
Swift 4+を使用している場合、これは完璧に機能する最良のソリューションです。時間の節約にご協力いただきありがとうございます。私はScheme Editorで遊んだことがありますが、Appleのアドバイスに従うことが今のところ最良の選択肢であり、前進しています。
AbuTaareq


-34

スキーム->診断を選択し、メインスレッドチェッカーを削除すると、警告が消えます。 スキームエディター


18
これは良い考えではないと思います。スレッドチェッカーが発見した問題があります。スレッドチェッカーを無効にすると、この問題と将来の問題が発見されなくなり、問題を修正するために将来の技術的負債が発生します。
ablarg 2017

1
メインスレッドでフレームバッファーをレンダリングできないため、実際には、OpenGLのesレンダリングを使用すると、これを行うことができます。正しい?
L.Peng 2017

1
ああ、それで警告が表示されなければ問題は存在しませんか?
チューリングテスト済み、2017年

11
「なぜ私の煙探知器は消え続けるのですか?」「バッテリーを外すだけで問題は解決しました。」
ジョンモンゴメリー

警告が表示されない場合、問題は存在しませんか?
S.ギッセル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.