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


107

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)")
        }
    }

1
에서 mapView(_:didChange)당신은 파견되는 print주요 큐에 문을. 아직 메인 대기열에 있지 않습니까? 그렇지 않은 경우 animate호출을 기본 대기열에도 전달해야합니다 . dispatchPrecondition(condition: .onQueue(.main))UI 업데이트 전에 몇 가지 를 삽입하는 것이 좋습니다 .
Rob

"내 코드의 메인 스레드에서 인터페이스 요소를 변경하지 않을 것이라고 거의 확신합니다." "... 모든 백그라운드 스레드에서"를 의미한다고 가정합니다.
Rob

2
당신의 문제가 아닙니다. 나는 그것이 그들의 끝에 있다고 생각합니다. "com.google.Maps.LabelingBehavior"에서 중지됩니다. 나는 똑같은 포블 렘을 가지고있다.
Tarvo Mäesepp 2017-06-26

2
안녕하세요, 그렇습니다. 문제는 Google에있는 것 같습니다. 곧 업데이트 된 버전을 출시 할 것입니다
MattBlack

1
이 답변에 봐 @MattBlack : stackoverflow.com/a/44392584/5912335
badhanganesh

답변:


54

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

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

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

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

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

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


1
@thibautnoah, "Google API와 함께 xcode 9 베타를 사용하고 있기 때문에 문제가 발생하고 있습니다."라고 표현하지 않았기 때문에 말씀하시는 건가요? 아니면 내 대답으로 해결되지 않는 유사한 버그에 직면했기 때문에?
ScottyBlades

7
Xcode 9는 xcode 8이 분명히 감지하지 못하는 몇 가지 스레딩 문제를 강조했습니다 (xcode 설정 때문인지 다른 것이 결정되어야하는지 여부). xcode 8로 다시 전환하는 것은 스레딩 문제를 무시하는 것과 동일하며 여전히 존재하며 해결되지 않았으므로 해결책이 아닙니다. 머리를 모래에 묻고 모든 것이 괜찮은 척하는 것입니다. 문제가 프레임 워크에서 발생하는 경우 문제를 제출하여 수정할 수 있도록하십시오.
thibaut noah

Xcode 9는 xcode 8이 감지하지 못하는 스레딩 문제를 감지하고 Xcode 9와 Google의 API를 함께 사용하면이 버그가 발생할 가능성이 있습니다. 이 버그는 여러 충돌에 대한 디버거에 있으며 xcode 8로 다시 전환 할 때 더 이상 충돌이 발생하지 않습니다.
ScottyBlades

요점은 스레드 검사기가 원인이 아닌 증상을 보여주고 있다는 것입니다. Xcode 9 베타가 원인이자 증상 전달자입니다. "xcode 8로 다시 전환 할 때 더 이상 충돌이 발생하지 않습니다." XCode 경고와 디버거 판독 값의 실제 충돌에는 차이가 있습니다. 이 오류는 경고 또는 충돌로 표시 될 수 있습니다. xcode 8로 다시 전환하면 충돌이 완전히 사라집니다. Xcode 9 베타는 좋은 이유로 베타라고합니다.
ScottyBlades

2
예 ... 많은 iOS 개발자가 무언가가 증상을 보이고 있다고해서 그 원인이 아니라는 것을 보증하는 것은 아닙니다. 나는 또한 애플이 실수를했을지도 모른다는 것을 받아들이 기 어렵다고 생각한다.
ScottyBlades

156

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

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

    Xcode 11.4.1

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

    이전 Xcode

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

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

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


4
고마워요, 30 분 정도 절약하세요.
Orange

10
어떤 이유로 Xcode 10.1에서 그렇게하면 무기력하고 코드 줄과 관련이없는 콜 스택 만 나타납니다. 2018-12-29 19 : 46 : 56.500629 + 0100 BedtimePrototype [1553 : 834478] [reports ] 메인 스레드 검사기 : 백그라운드 스레드에서 호출되는 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거나 간단히 주석 처리하고 다시 테스트하여 어느 것이 문제가 있는지 알아 냈습니다.
John Pang

2
또한 SVProgressHUD.show를 주석 처리하여 경고를 제거했습니다. 이 호출을 DispatchQueue.main.async로 래핑해도 경고가 제거되지 않았습니다. v2.2.5에서 포드를 사용합니다.이 스레드는 문제를 더 잘 이해하는 데 도움이 될 수 있습니다. github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir

1
xcode 11.4.1에는 "Pause on Issues"확인란이 없습니다. 편집 : 메인 스레드 검사기 옆에 작은 화살표가 있습니다. 클릭하면 중단 점이 추가됩니다.
ChrisO

47

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


4
그래, 난 이미 사용했지만 경고는 여전히 존재
MattBlack

@Pang, 기본 UI 코드가 아닌 인쇄에 사용됩니다.
Toma

4
온 UI를 수정하는 모든 것을 마무리하려고 @MattBlackDispatchQueue.main.async {}
토마

@ user6603599 - 작품 마법처럼
스리

3

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

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


1
Swift 4+를 사용하는 경우이 솔루션이 완벽하게 작동합니다. 시간을 절약 할 수 있도록 도와 주셔서 감사합니다. 나는 Scheme Editor를 가지고 놀았지만 Apple의 조언을 따르는 것이 최선의 선택이며 앞으로 나아가고 있습니다.
AbuTaareq


-34

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


18
나는 이것이 좋은 생각이라고 생각하지 않습니다. 여기에 스레드 검사기가 발견 한 문제가 있습니다. 스레드 검사기를 비활성화하면이 문제와 향후 문제가 발견되지 않고 향후 기술 부채가 발생하여 문제를 해결할 수 있습니다.
ablarg

1
사실, 제 요점은 우리가 메인 스레드에서 프레임 버퍼를 렌더링 할 수 없기 때문에 OpenGL es 렌더링을 사용할 때 이것을 할 수 있다는 것입니다. 권리?
L.Peng

1
아, 그렇다면 경고가 나타나지 않으면 문제가 존재하지 않습니까?
turingtested

11
"왜 연기 감지기가 계속 꺼 지나요?" "배터리 만 제거하면 문제가 해결됩니다."
John Montgomery

경고가 나타나지 않으면 문제가 존재하지 않습니까?
S. Gissel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.