Проверка основного потока: API пользовательского интерфейса вызывается в фоновом потоке: - [UIApplication applicationState]

Я использую карты Google в бета-версии Xcode 9, iOS 11.

Я получаю следующее сообщение об ошибке в журнале:

Проверка основного потока: 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)")
        }
    }

person MattBlack    schedule 26.06.2017    source источник
comment
В mapView(_:didChange) вы отправляете print операторы в главную очередь. Вы еще не в основной очереди? В противном случае вы также должны отправить вызов animate в основную очередь. Я бы посоветовал вставить несколько dispatchPrecondition(condition: .onQueue(.main)) перед этими обновлениями пользовательского интерфейса, на всякий случай.   -  person Rob    schedule 26.06.2017
comment
Вы сказали, что я почти уверен, что не изменяю какие-либо элементы интерфейса из основного потока в моем коде. Я полагаю, вы имели в виду ... из любого фонового потока.   -  person Rob    schedule 26.06.2017
comment
Кстати, вы можете отредактировать свою схему, перейти на страницу диагностики и выбрать паузу при обнаружении проблем в разделе «Проверка основного потока». Это может помочь сузить источник проблемы.   -  person Rob    schedule 26.06.2017
comment
Не твоя проблема. Я думаю, это в их конце. Он останавливается в com.google.Maps.LabelingBehavior. У меня такая же проблема.   -  person Tarvo Mäesepp    schedule 27.06.2017
comment
Я потратил целую вечность, пытаясь понять это, но я согласен с вашим выводом. Спасибо, @Rob!   -  person MattBlack    schedule 27.06.2017
comment
@MattBlack, мне очень любопытно, помог ли мой ответ решить проблему? Я сталкивался с этой проблемой несколько раз, если она не решит ее для вас, у меня будет больше данных об этом типе ошибки.   -  person ScottyBlades    schedule 28.08.2017
comment
Привет, да, проблема, похоже, связана с Google, надеюсь, они скоро выпустят обновленную версию   -  person MattBlack    schedule 29.08.2017
comment
@MattBlack Взгляните на этот ответ: stackoverflow.com/a/44392584/5912335   -  person badhanganesh    schedule 22.09.2017
comment
У меня также была эта проблема с установленной вручную версией Google Maps. Как только я переключился на управляемую версию CocoaPods, ошибка исчезла. Предполагая, что Google исправил эту ошибку в более поздних версиях своей платформы.   -  person wildcat12    schedule 06.10.2018


Ответы (6)


Во-первых, убедитесь, что вызовы карт Google и изменения пользовательского интерфейса вызываются из основного потока.

Вы можете включить параметр Thread Sanitizer в Xcode, выполнив следующие действия:

Скриншот

Вы можете поместить оскорбительные строки в основной поток следующим образом:

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

Также обновите свою текущую версию карт Google. Карты Google пришлось сделать пару обновлений для средства проверки потоков.

На вопрос: почему это происходит? Я думаю, что Apple добавила утверждение для крайнего случая, который Google затем пришлось обновить стручок для.

person ScottyBlades    schedule 28.08.2017
comment
@thibautnoah, вы говорите, потому что я не сформулировал это, поскольку проблема (проблема) возникает из-за того, что вы используете бета-версию xcode 9 в сочетании с API Google? Или потому, что вы столкнулись с похожей ошибкой, которая не решена моим ответом? - person ScottyBlades; 04.09.2017
comment
Xcode 9 выдвинул на первый план некоторые проблемы с потоками, которые xcode 8, по-видимому, не обнаруживает (связано ли это с настройками xcode или другими вещами, которые необходимо определить). Возвращение к xcode 8 эквивалентно игнорированию ваших проблем с потоками, они все еще существуют и не решены, поэтому это не решение, вы просто зарываете голову в песок и делаете вид, что все в порядке. Если проблема связана с фреймворком, отправьте сообщение о проблеме, чтобы ее можно было исправить. - person thibaut noah; 04.09.2017
comment
Xcode 9 обнаруживает проблемы с потоками, которые xcode 8 не может обнаружить, И Xcode 9 в сочетании с API Google, вероятно, вызывает эту ошибку. Эта ошибка обнаруживается в отладчике для нескольких сбоев, И сбои больше не происходят, когда вы переключаетесь обратно на xcode 8. - person ScottyBlades; 04.09.2017
comment
Вы имеете в виду, что средство проверки потоков показывает симптом, а не причину. Я говорю, что бета-версия Xcode 9 является одновременно причиной и коммуникатором симптомов. сбои больше не происходят, когда вы переключаетесь обратно на xcode 8. Есть разница между предупреждениями XCode и фактическими сбоями с показаниями отладчика. Эта ошибка может отображаться как предупреждение ИЛИ сбой. Сбой полностью исчезает при переключении обратно на xcode 8. Бета-версия Xcode 9 не зря называется бета-версией. - person ScottyBlades; 05.09.2017
comment
Вовсе нет, я говорю, что xcode 9 имеет лучшую проверку потоков (также новый быстрый api, поскольку он поставляется для ios 11 с swift 3.3 и swift 4, а не только потоки на самом деле). Отсутствие проблемы в xcode 8 НЕ означает, что проблемы нет, потому что она есть! Это будет просто очевидно с xcode 9, в то время как с xcode 8 вы не будете знать, что на самом деле проблема. Основная причина проблемы здесь либо в вашем коде, либо в фреймворке Google, а НЕ в xcode 9. Но это ваш код, и если вы решите проигнорировать проблему, которая зависит от вас, я сказал свою часть - person thibaut noah; 05.09.2017
comment
Позвольте нам продолжить это обсуждение в чате. - person thibaut noah; 05.09.2017
comment
Да ... Я думаю, что многим разработчикам iOS трудно понять, что то, что что-то демонстрирует симптом, не означает, что он гарантированно не является причиной. Я также думаю, что трудно согласиться с тем, что Apple могла когда-либо совершить ошибку. - person ScottyBlades; 20.09.2017
comment
Apple сделала много ошибок, дело не в этом, и вы это знаете. Это не значит, что это не причина, но явное игнорирование того факта, что существует высокая вероятность того, что в коде действительно есть проблема с потоками, - это как я сказал, прежде чем покупать вашу голову в песке. Думал, что я ясно дал понять раньше. - person thibaut noah; 25.09.2017

Иногда сложно найти код пользовательского интерфейса, который не выполняется в основном потоке. Вы можете использовать описанный ниже трюк, чтобы найти и исправить.

  1. Выберите Edit Scheme -> Diagnostics, отметьте Main Thread Checker.

    Xcode 11.4.1

    Щелкните маленькую стрелку рядом со средством проверки основного потока, чтобы создать точку останова средства проверки основного потока. введите описание изображения здесь

    Предыдущий Xcode

    Отметьте «Пауза» при возникновении проблем. введите описание изображения здесь

  2. Запустите приложение iOS, чтобы воспроизвести эту проблему. (Xcode должен остановиться на первой проблеме.)  введите описание изображения здесь

  3. Оберните код, изменяющий пользовательский интерфейс, в DispatchQueue.main.async {}  введите описание изображения здесь

person UnchartedWorks    schedule 25.04.2018
comment
Спасибо, сэкономьте, может быть, 30 минут. - person Orange; 21.06.2018
comment
Пробовал то же самое, но он не останавливается на линии проблемы. Любое другое решение? - person Vijay; 10.07.2018
comment
Сложно сказать. Я просто полагаюсь на средство проверки основного потока и решаю только те проблемы, на которые жалуется средство проверки основного потока, и этого достаточно для меня. - person UnchartedWorks; 11.07.2018
comment
По какой-то причине, когда я делаю это в Xcode 10.1, я получаю только беспомощный стек вызовов, который я не могу соотнести со строкой кода: 2018-12-29 19: 46: 56.500629 + 0100 BedtimePrototype [1553: 834478] [сообщает ] Проверка основного потока: API пользовательского интерфейса, вызываемый в фоновом потоке: - [UIApplication applicationState] PID: 1553, TID: 834478, имя потока: com.apple.CoreMotion.MotionThread, имя очереди: com.apple.root.default-qos. сверхкоммит, QoS: 0 - person Vilmir; 29.12.2018
comment
У меня также есть стек вызовов, который выглядит беспомощным. С левой стороны он остановился на "com.apple.CoreMotion.MotionThread(23)", затем я также проверяю все другие потоки. В Thread 1 кое-что привлекло мое внимание: это SVProgressHUD (библиотека просмотра прогресса, которую я использовал). Итак, я знаю, что это вызов SVProgressHUD.show() где-то в целевом контроллере представления. Затем либо заключите каждое появление в DispatchQueue.main.async, либо просто закомментируйте, проверьте еще раз, и я выяснил, какой из них проблематичный. - person John Pang; 20.02.2019
comment
@JohnPang Странно, здесь произошло то же самое, но с MBProgressHUD. Спасибо за совет! - person Robbie Trencheny; 19.04.2019
comment
Я также избавился от предупреждения, закомментировав SVProgressHUD.show. Помещение этого вызова в DispatchQueue.main.async не избавило от предупреждения. Я использую модуль в версии 2.2.5. Эта ветка может помочь лучше понять проблему: github.com/SVProgressHUD / SVProgressHUD / issues / 950 - person Vilmir; 20.04.2019
comment
Потрясающе, это сэкономило мне время;) Спасибо - person steveSarsawa; 02.01.2020
comment
Флажка «Приостановить при возникновении проблем» у меня нет в xcode 11.4.1. Изменить: я нашел маленькую стрелку рядом с программой проверки основного потока. Щелчок, который добавляет вам точку останова. - person ChrisO; 19.05.2020
comment
Похоже, это исчезло в Xcode 12. Кто-нибудь знает, куда он переместился? - person below; 30.09.2020

Оберните строки кода, изменяющие пользовательский интерфейс, в DispatchQueue.main.async {}, чтобы убедиться, что они выполняются в основном потоке. В противном случае вы можете вызывать их из фонового потока, где модификации пользовательского интерфейса не разрешены. Все такие строки кода должны выполняться из основного потока.

person Toma    schedule 05.07.2017
comment
да, я уже использовал это, но предупреждение все еще присутствует - person MattBlack; 06.07.2017
comment
@Pang, он используется для печати, а не для основного кода пользовательского интерфейса. - person Toma; 06.07.2017
comment
@MattBlack пытается обернуть все, что изменяет пользовательский интерфейс, на DispatchQueue.main.async {} - person Toma; 06.07.2017
comment
@ user6603599-Работает как шарм - person IOSDevops; 04.01.2018

Перейдите по этой ссылке https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Для меня это сработало, когда я позвонил из блока.

person Krishna Chaitanya Bandaru    schedule 28.11.2017
comment
Если вы используете Swift 4+, это лучшее решение, которое отлично работает, спасибо, что помогли мне сэкономить время. Я играл с редактором схем, но сейчас лучший вариант - следовать совету Apple и двигаться вперед. - person AbuTaareq; 29.01.2018
comment
К сожалению, сейчас это мертвая ссылка. - person Marcy; 14.09.2020

Я думаю, что решение уже дано, потому что моя проблема - клавиатура в пути.

UIKeyboardTaskQueue можно вызывать только из основного потока < / а>

person gamal    schedule 14.06.2019

Выберите схему -> Диагностика, удалите средство проверки основного потока, после чего предупреждение исчезнет. редактор схем

person L.Peng    schedule 22.08.2017
comment
Не думаю, что это хорошая идея. Здесь есть проблема, которую обнаружила программа проверки потоков. Отключение средства проверки потоков позволит не обнаруживать эту и будущие проблемы, а в будущем возникнет техническая задолженность по устранению проблем. - person ablarg; 25.08.2017
comment
На самом деле, я хочу сказать, что мы можем сделать это, используя рендеринг OpenGL es, потому что мы не можем рендерить буфер кадра в основном потоке. Правильно? - person L.Peng; 29.08.2017
comment
Ах, значит, если предупреждения не появилось, значит, проблемы не существует? - person turingtested; 24.11.2017
comment
Почему мой детектор дыма продолжает срабатывать? Просто извлеките аккумулятор, проблема решена. - person John Montgomery; 04.10.2018
comment
Если предупреждение не появляется, значит, проблемы не существует? - person S. Gissel; 06.01.2020