主线程检查器:在后台线程上调用的UI API:-[UIApplication applicationState]


107

我正在Xcode 9 beta,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)2015年

您说:“几乎可以肯定,我不会在代码中更改主线程中的任何接口元素。” 我假设您的意思是“ ...来自任何后台线程”。
罗布(Rob)

2
不是你的问题。我觉得这是他们的尽头。它停在“ com.google.Maps.LabelingBehavior”中。我有同样的问题。
TarvoMäesepp17年

2
嗨,是的,问题似乎出在Google
身上

1
@MattBlack看看这个答案:stackoverflow.com/a/44392584/5912335
badhanganesh

Answers:


54

首先,请确保从主线程中调用了Google地图和ui更改。

您可以启用Thread Sanitizer 查找有问题的行。

您可以使用以下命令在主线程上添加冒犯的行:

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

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

问一个问题:“为什么会这样?” 我认为苹果为一个边缘案例添加了一个断言,然后谷歌不得不为其更新pod。


1
@thibautnoah,您是说是因为我未将其表述为“它(问题)正在发生,因为您正在将xcode 9 beta与Google的API结合使用?” 还是因为您遇到类似的错误而我的答案无法解决?
ScottyBlades

7
Xcode 9突出显示了xcode 8显然无法检测到的一些线程问题(无论是由于xcode设置还是要确定另一件事)。切换回xcode 8等同于忽略线程问题,这些问题仍然存在并且没有解决,因此这不是解决方案,您只是将头埋在沙子里并假装一切正常。如果问题来自框架,请提交问题,以便可以解决。
thibaut noah

Xcode 9会检测到xcode 8无法检测到的线程问题,并且Xcode 9与Google的API结合可能会导致此错误。这个bug在调试器多选址崩溃,当你切换回的Xcode 8.事故不再发生
ScottyBlades

您要指出的是,线程检查器显示的是症状而不是原因。我说的是Xcode 9 beta既是原因,又是症状传达者。“当您切换回xcode 8时,崩溃不再发生”。XCode警告和调试器读数的实际崩溃之间有区别。该错误可能显示为警告或崩溃。切换回xcode 8时,崩溃完全消失了。出于充分的理由,Xcode 9 beta被称为beta。
ScottyBlades

2
是的...我认为对于许多ios开发人员来说,仅因为某些东西正在显示症状就很难看到它,但这并不意味着它也不是原因。我认为也很难接受苹果可能曾经犯过的错误。
ScottyBlades

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()对目标视图控制器中某处的调用。然后要么将每个外观包装起来,DispatchQueue.main.async要么简单地注释掉,再次进行测试,然后我发现哪个是有问题的。

2
我还通过注释掉SVProgressHUD.show摆脱了警告。将此调用包装到DispatchQueue.main.async中并没有摆脱警告。我在v2.2.5中使用了pod。该线程可以帮助您更好地理解问题:github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir

1
xcode 11.4.1中没有“问题暂停”复选框。编辑:我在主线程检查器旁边找到了一个小箭头。单击可为您添加一个断点。
克里斯·奥

47

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


4
是的,我已经使用过了,但是警告仍然存在
MattBlack '17

@Pang,它用于打印内容,而不是主要的UI代码。
Toma'7

4
@MattBlack尝试将所有修改UI的内容包装在DispatchQueue.main.async {}
Toma

@ user6603599-像魅力一样工作
Sree



-34

选择方案->诊断,移除主线程检查器,然后该警告将消失。 方案编辑


18
我认为这不是一个好主意。这里存在线程检查器发现的问题。禁用线程检查器将使此问题和将来的问题不被发现,并导致将来修复该问题时需要承担技术债务。
ablarg

1
实际上,我的意思是,当我们使用OpenGL es渲染时我们可以做到这一点,因为我们无法在主线程中渲染帧缓冲区。对?
L.Peng

1
嗯,所以如果没有出现警告,就不存在问题吗?
turingtest '17

11
“为什么我的烟雾探测器不断熄灭?” “只需取出电池,问题就解决了。”
约翰·蒙哥马利

如果未出现警告,则说明问题不存在?
S. Gissel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.