Pemeriksa Utas Utama: API UI dipanggil pada utas latar belakang: - [UIApplication applicationState]

107

Saya menggunakan peta google di Xcode 9 beta, iOS 11.

Saya mendapatkan kesalahan yang dikeluarkan ke log sebagai berikut:

Pemeriksa Utas Utama: API UI memanggil utas latar belakang: - [UIApplication applicationState] PID: 4442, TID: 837820, Nama utas: com.google.Maps.LabelingBehavior, Nama antrean: com.apple.root.default-qos.overcommit , QoS: 21

Mengapa ini terjadi karena saya hampir yakin saya tidak mengubah elemen antarmuka apa pun dari utas utama dalam kode saya.

 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)")
        }
    }
MattBlack
sumber
1
Dalam mapView(_:didChange)Anda mengirimkan printpernyataan ke antrian utama. Apakah Anda belum berada di antrian utama? Jika tidak, Anda juga harus mengirimkan animatepanggilan ke antrean utama. Saya sarankan untuk memasukkan beberapa dispatchPrecondition(condition: .onQueue(.main))sebelum pembaruan UI tersebut, hanya untuk memastikan.
Rob
Anda berkata "Saya hampir yakin saya tidak mengubah elemen antarmuka apa pun dari utas utama dalam kode saya." Saya berasumsi bahwa yang Anda maksud adalah "... dari utas latar belakang mana pun."
Rob
2
Bukan masalahmu. Saya pikir itu ada di ujung mereka. Ini berhenti di "com.google.Maps.LabelingBehavior". Saya memiliki poblem yang sama.
Tarvo Mäesepp
2
Hai, ya, masalahnya terletak pada google, semoga mereka akan segera merilis versi yang diperbarui
MattBlack
1
@MattBlack Lihatlah jawaban ini: stackoverflow.com/a/44392584/5912335
badhanganesh

Jawaban:

54

Pertama, pastikan pemanggilan Google Maps dan perubahan UI Anda dipanggil dari utas utama.

Anda dapat mengaktifkan Pembersih Benang untuk menemukan garis yang menyinggung.

Anda dapat meletakkan garis menyinggung di utas utama dengan yang berikut:

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

Juga, perbarui versi peta google Anda saat ini. Peta Google harus membuat beberapa pembaruan untuk pemeriksa utas.

Untuk pertanyaan: "Mengapa ini terjadi?" Saya pikir Apple menambahkan pernyataan untuk kasus tepi yang kemudian harus diperbarui oleh Google untuk pod mereka.

ScottyBlades
sumber
1
@thibautnoah, apakah Anda mengatakan itu karena saya tidak mengucapkannya sebagai "itu (masalah) terjadi karena Anda menggunakan xcode 9 beta dalam kombinasi dengan API Google?" Atau karena Anda menghadapi bug serupa yang tidak terpecahkan oleh jawaban saya?
ScottyBlades
7
Xcode 9 menyoroti beberapa masalah threading yang tampaknya tidak terdeteksi oleh xcode 8 (apakah itu karena pengaturan xcode atau hal lain yang akan ditentukan). Beralih kembali ke xcode 8 sama dengan mengabaikan masalah threading Anda, mereka masih ada dan belum terpecahkan, jadi ini bukan solusi, Anda hanya mengubur kepala di pasir dan berpura-pura semuanya baik-baik saja. Jika masalah berasal dari kerangka kerja, harap kirimkan masalah agar dapat diperbaiki.
thibaut noah
Xcode 9 mendeteksi masalah threading yang tidak dideteksi oleh xcode 8, DAN Xcode 9 yang dikombinasikan dengan API Google kemungkinan besar menyebabkan bug ini. Bug ini ditempatkan di debugger untuk beberapa kerusakan DAN kerusakan tidak lagi terjadi saat Anda beralih kembali ke xcode 8.
ScottyBlades
Maksud Anda adalah bahwa pemeriksa utas menunjukkan gejala bukan penyebabnya. Saya mengatakan Xcode 9 beta adalah penyebab DAN komunikator gejala. "crash tidak lagi terjadi saat Anda beralih kembali ke xcode 8". Ada perbedaan antara peringatan XCode dan error aktual dengan pembacaan debugger. Kesalahan ini dapat muncul sebagai peringatan ATAU kerusakan. Kerusakan hilang sepenuhnya ketika beralih kembali ke xcode 8. Xcode 9 beta disebut beta karena alasan yang bagus.
ScottyBlades
2
Ya ... Saya rasa sulit bagi banyak pengembang ios untuk melihat bahwa hanya karena ada sesuatu yang menunjukkan gejala, bukan berarti dijamin bukan penyebabnya juga. Saya pikir juga sulit untuk menerima bahwa Apple mungkin pernah melakukan kesalahan.
ScottyBlades
156

Sulit untuk menemukan kode UI yang terkadang tidak dieksekusi di utas utama. Anda dapat menggunakan trik di bawah ini untuk menemukan dan memperbaikinya.

  1. Pilih Edit Scheme -> Diagnostics, centang Main Thread Checker.

    Xcode 11.4.1

    Klik tanda panah kecil di sebelah Main Thread Checker untuk membuat titik putus Main Thread Checker. masukkan deskripsi gambar di sini

    Xcode sebelumnya

    Centang pada Pause on issues. masukkan deskripsi gambar di sini

  2. Jalankan aplikasi iOS Anda untuk mereproduksi masalah ini. (Xcode harus berhenti pada masalah pertama.) masukkan deskripsi gambar di sini

  3. Gabungkan kode yang mengubah UI DispatchQueue.main.async {} masukkan deskripsi gambar di sini

UnchartedWorks
sumber
4
Terima kasih, hemat saya mungkin 30 menit.
Orange
10
Untuk beberapa alasan, ketika saya melakukannya di Xcode 10.1, saya hanya mendapatkan callstack yang tidak berdaya dan saya tidak dapat menghubungkan ke baris kode: 2018-12-29 19: 46: 56.500629 + 0100 BedtimePrototype [1553: 834478] [laporan ] Pemeriksa Utas Utama: API UI dipanggil pada utas latar belakang: - [UIApplication applicationState] PID: 1553, TID: 834478, Nama utas: com.apple.CoreMotion.MotionThread, Nama antrian: com.apple.root.default-qos. overcommit, QoS: 0
Vilmir
1
Saya juga mendapat tumpukan panggilan yang terlihat tidak berdaya. Di sisi kiri berhenti "com.apple.CoreMotion.MotionThread(23)", lalu saya periksa semua utas lainnya juga. Dalam Thread 1sesuatu yang menarik perhatian saya: itu adalah SVProgressHUD (perpustakaan tampilan kemajuan yang saya gunakan). Jadi, saya tahu ini adalah panggilan ke SVProgressHUD.show()suatu tempat di pengontrol tampilan target. Kemudian bungkus setiap penampilan dengan DispatchQueue.main.asyncatau cukup beri komentar, uji lagi dan saya menemukan mana yang bermasalah.
John Pang
2
Saya juga menghilangkan peringatan itu dengan mengomentari SVProgressHUD.show. Membungkus panggilan ini menjadi DispatchQueue.main.async tidak menghilangkan peringatan tersebut. Saya menggunakan pod di v2.2.5 Utas ini dapat membantu memahami masalah dengan lebih baik: github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir
1
Kotak centang "Jeda saat Masalah" tidak ada untuk saya di xcode 11.4.1. Edit: Saya menemukan panah kecil di sebelah Main Thread Checker. Mengklik yang menambahkan breakpoint untuk Anda.
ChrisO
47

Gabungkan baris kode yang mengubah UI DispatchQueue.main.async {}untuk memastikannya dijalankan di utas utama. Jika tidak, Anda mungkin memanggil mereka dari thread latar belakang, yang tidak mengizinkan modifikasi UI. Semua baris kode tersebut harus dijalankan dari utas utama.

Toma
sumber
4
ya saya sudah menggunakan itu tetapi peringatannya masih ada
MattBlack
@Pang, ini digunakan untuk mencetak sesuatu, bukan untuk kode UI utama.
Toma
4
@MattBlack mencoba membungkus semua hal yang memodifikasi UI padaDispatchQueue.main.async {}
Toma
@ user6603599-Bekerja seperti pesona
Sree
3

Lihat tautan ini https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Bagi saya ini berhasil ketika saya menelepon dari blok.

Krishna Chaitanya Bandaru
sumber
1
Jika Anda menggunakan Swift 4+, ini adalah solusi terbaik yang berfungsi sempurna, terima kasih telah membantu saya menghemat waktu saya. Saya telah bermain dengan Editor Skema tetapi mengikuti saran Apple adalah pilihan terbaik sekarang dan bergerak maju.
AbuTaareq
-34

Pilih skema -> Diagnosis, hapus pemeriksa utas utama, maka peringatan akan hilang. editor skema

L.Peng
sumber
18
Saya rasa ini bukan ide yang bagus. Ada masalah di sini yang ditemukan oleh pemeriksa utas. Menonaktifkan pemeriksa utas akan memungkinkan masalah ini dan masa depan tidak ditemukan, dan menyebabkan hutang teknis di masa depan timbul untuk memperbaiki masalah.
ablarg
1
Sebenarnya, maksud saya adalah kita bisa melakukan ini saat kita menggunakan OpenGL es rendering, karena kita tidak bisa membuat buffer frame di thread utama. Baik?
L.Peng
1
Ah, jadi jika waring tidak muncul, masalahnya tidak ada?
diuji
11
"Mengapa detektor asap saya terus mati?" "Lepaskan saja baterainya, masalah terselesaikan."
John Montgomery
Jika peringatan tidak muncul, masalahnya tidak ada?
S. Gissel