[swift] 메인 스레드 검사기 : 백그라운드 스레드에서 호출 된 UI API :-[UIApplication applicationState]

Xcode 9 베타, 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)")
        }
    }



답변

먼저 Google지도 및 UI 변경의 호출이 기본 스레드에서 호출되는지 확인합니다.

Thread Sanitizer 를 사용하여 문제가되는 줄을 찾을 수 있습니다.

다음을 사용하여 주 스레드에 문제가되는 줄을 넣을 수 있습니다.

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

또한 현재 버전의 Google지도를 업데이트하세요. Google지도는 스레드 검사기를 위해 몇 가지 업데이트를해야했습니다.

질문 : “왜 이런 일이 발생합니까?” 나는 애플 이 구글이 그들의 포드를 업데이트해야하는 엣지 케이스 에 대한 주장 을 추가했다고 생각한다 .


답변

때때로 메인 스레드에서 실행되지 않는 UI 코드를 찾기가 어렵습니다. 아래 트릭을 사용하여 찾아서 수정할 수 있습니다.

  1. 구성표 편집-> 진단을 선택하고 주 스레드 검사기를 선택합니다.

    Xcode 11.4.1

    주 스레드 검사기 옆에있는 작은 화살표를 클릭하여 주 스레드 검사기 중단 점을 만듭니다.
    여기에 이미지 설명 입력

    이전 Xcode

    Pause on issues를 선택합니다.
    여기에 이미지 설명 입력

  2. 이 문제를 재현하려면 iOS 애플리케이션을 실행하십시오. (Xcode는 첫 번째 문제에서 일시 중지되어야합니다.)
    여기에 이미지 설명 입력

  3. UI를 수정하는 코드를 DispatchQueue.main.async {}
    여기에 이미지 설명 입력


답변

UI를 수정하는 코드 줄을 DispatchQueue.main.async {}메인 스레드에서 실행되도록 . 그렇지 않으면 UI 수정이 허용되지 않는 백그라운드 스레드에서 호출 할 수 있습니다. 이러한 모든 코드 줄은 주 스레드에서 실행해야합니다.


답변

이 링크 https://developer.apple.com/documentation/code_diagnostics/main_thread_checker를 참조하십시오.

나를 위해 이것은 내가 블록에서 전화했을 때 작동했습니다.


답변

나는 해결책이 이미 주어 졌다고 생각한다. 내 문제는 곧 키보드이다.

UIKeyboardTaskQueue는 기본 스레드에서만 호출 할 수 있습니다.


답변

구성표-> 진단을 선택하고 주 스레드 검사기를 제거하면 경고가 사라집니다.
구성표 편집기


답변