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