【问题标题】:Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]主线程检查器:在后台线程上调用的 UI API:-[UIApplication applicationState]
【发布时间】:2017-11-29 18:27:56
【问题描述】:

我在 Xcode 9 beta、iOS 11 中使用谷歌地图。

我收到如下错误输出到日志:

主线程检查器:在后台线程上调用的 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)")
        }
    }

【问题讨论】:

  • mapView(_:didChange) 中,您将print 语句分派到主队列。你不是已经在主队列上了吗?如果没有,您也必须将animate 调用发送到主队列。我建议在这些 UI 更新之前插入一些 dispatchPrecondition(condition: .onQueue(.main)),以确保。
  • 您说“我几乎可以肯定我不会从我的代码中的主线程更改任何界面元素。”我假设您的意思是“......来自任何后台线程。”
  • 不是你的问题。我认为这是在他们的尽头。它停在“com.google.Maps.LabelingBehavior”中。我有同样的问题。
  • 您好,是的,问题似乎出在 google 上,希望他们能尽快发布更新版本
  • @MattBlack 看看这个答案:stackoverflow.com/a/44392584/5912335

标签: swift google-maps xcode9-beta


【解决方案1】:

有时很难找到不在主线程中执行的 UI 代码。您可以使用下面的技巧找到并修复它。

  1. 选择 Edit Scheme -> Diagnostics,勾选 Main Thread Checker。

    Xcode 11.4.1

    单击主线程检查器旁边的小箭头以创建主线程检查器断点。

    以前的 Xcode

    勾选暂停问题。

  2. 运行您的 iOS 应用程序以重现此问题。 (Xcode 应该在第一个问题上暂停。)

  3. 将修改 UI 的代码封装在 DispatchQueue.main.async {}

【讨论】:

  • 谢谢,也许可以节省我 30 分钟。
  • 出于某种原因,当我在 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.overcommit,QoS:0
  • 我也得到了一个看起来很无奈的调用栈。在左侧,它停在"com.apple.CoreMotion.MotionThread(23)",然后我也检查了所有其他线程。在Thread 1 中引起了我的注意:它是 SVProgressHUD(我使用的进度视图库)。所以,我知道这是对目标视图控制器某处的SVProgressHUD.show() 的调用。然后用DispatchQueue.main.async 包裹每个外观,或者简单地注释掉,再次测试,我发现哪个有问题。
  • 我还通过注释掉 SVProgressHUD.show 摆脱了警告。将此调用包装到 DispatchQueue.main.async 并没有消除警告。我在 v2.2.5 中使用 pod 这个线程可以帮助更好地理解问题:github.com/SVProgressHUD/SVProgressHUD/issues/950
  • xcode 11.4.1 中没有“问题暂停”复选框。编辑:我在主线程检查器旁边发现了一个小箭头。单击它会为您添加一个断点。
【解决方案2】:

首先,确保从主线程调用谷歌地图和用户界面更改。

您可以使用以下步骤在 Xcode 中启用Thread Sanitizer 选项:

您可以在主线程中添加以下内容:

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

另外,更新您当前版本的谷歌地图。 Google 地图必须对线程检查器进行一些更新。

对于问题:“为什么会发生这种情况?”我认为 Apple 为边缘案例添加了 assertion,然后 Google 必须更新其 pod。

【讨论】:

  • @thibautnoah,您是说因为我没有将其表述为“它(问题)正在发生,因为您将 xcode 9 beta 与 Google 的 API 结合使用?”还是因为您面临我的回答无法解决的类似错误?
  • Xcode 9 突出了一些 xcode 8 显然没有检测到的线程问题(无论是由于 xcode 设置还是其他有待确定的问题)。切换回 xcode 8 相当于忽略了你的线程问题,它们仍然存在并且没有解决,因此这不是一个解决方案,你只是把头埋在沙子里,假装一切正常。如果问题来自框架,请提交问题以便修复。
  • Xcode 9 检测到 xcode 8 无法检测到的线程问题,并且 Xcode 9 与 Google 的 API 结合可能确实会导致此错误。此错误位于调试器中,用于多次崩溃,并且当您切换回 xcode 8 时不再发生崩溃。
  • 你的意思是线程检查器显示的是症状而不是原因。我是说 Xcode 9 beta 既是原因又是症状传播者。 “当您切换回 xcode 8 时,不再发生崩溃”。 XCode 警告和带有调试器读数的实际崩溃之间存在差异。此错误可能显示为警告或崩溃。当切换回 xcode 8 时,崩溃完全消失了。Xcode 9 beta 被称为 beta 是有充分理由的。
  • 是的...我认为对于许多 ios 开发人员来说,仅仅因为某些东西正在显示症状,并不意味着它也可以保证不是原因。我认为也很难接受苹果可能曾经犯过错误。
【解决方案3】:

将修改 UI 的代码行封装在 DispatchQueue.main.async {} 中,以确保它们在主线程上执行。否则,您可能会从不允许修改 UI 的后台线程调用它们。所有这些代码行都必须从主线程执行。

【讨论】:

  • 是的,我已经使用过,但警告仍然存在
  • @Pang,它是用来打印东西的,不是主要的UI代码。
  • @MattBlack 尝试在DispatchQueue.main.async {}上包装所有修改 UI 的东西
  • @user6603599-像魅力一样工作
【解决方案4】:

参考这个链接 https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

对我来说,当我从块中调用时,这很有效。

【讨论】:

  • 如果您使用的是 Swift 4+,这是最完美的解决方案,感谢您帮助我节省了时间。我玩过 Scheme Editor,但现在遵循 Apple 的建议是最好的选择。
  • 不幸的是,现在这是一个死链接。
【解决方案5】:

我认为解决方案已经给出, 我的问题是键盘在路上。

UIKeyboardTaskQueue may only be called from the main thread

【讨论】:

    【解决方案6】:

    选择方案 -> 诊断,删除主线程检查器,然后警告将消失。 scheme editor

    【讨论】:

    • 我认为这不是一个好主意。这里有一个线程检查器发现的问题。禁用线程检查器将使这个和未来的问题未被发现,并导致未来产生技术债务来解决这些问题。
    • 其实我的意思是我们在使用OpenGL es渲染时可以做到这一点,因为我们不能在主线程中渲染帧缓冲区。对吗?
    • 啊,如果没有出现警告,问题就不存在了?
    • "为什么我的烟雾探测器一直响?" “只需卸下电池,问题就解决了。”
    • 如果没有出现警告说明问题不存在?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多