ตัวตรวจสอบเธรดหลัก: UI API เรียกบนเธรดพื้นหลัง: - [UIApplication applicationState]


107

ฉันใช้ Google Maps ใน 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)")
        }
    }

1
ในmapView(_:didChange)คุณกำลังเยี่ยงอย่างprintงบไปยังคิวหลัก คุณไม่ได้อยู่ในคิวหลักหรือไม่? ถ้าไม่คุณต้องส่งanimateสายไปยังคิวหลักด้วย ฉันขอแนะนำให้แทรกบางส่วนdispatchPrecondition(condition: .onQueue(.main))ก่อนการอัปเดต UI เพื่อให้แน่ใจ
Rob

คุณบอกว่า "ฉันเกือบจะแน่ใจแล้วว่าฉันไม่ได้แก้ไของค์ประกอบอินเทอร์เฟซใด ๆ จากเธรดหลักในโค้ดของฉัน" ฉันคิดว่าคุณหมายถึง "... จากเธรดพื้นหลังใด ๆ "
Rob

2
ไม่ใช่ปัญหาของคุณ ฉันคือจุดจบของพวกเขา จะหยุดใน "com.google.Maps.LabelingBehavior" ฉันมีปัญหาเดียวกัน
Tarvo Mäesepp

2
สวัสดีใช่แล้วปัญหาดูเหมือนจะอยู่กับ Google หวังว่าพวกเขาจะปล่อยเวอร์ชันที่อัปเดตเร็ว ๆ นี้
MattBlack

1
@MattBlack ดูคำตอบนี้stackoverflow.com/a/44392584/5912335
badhanganesh

คำตอบ:


57

ขั้นแรกตรวจสอบให้แน่ใจว่าการเรียกใช้ Google Maps และการเปลี่ยนแปลง UI ของคุณถูกเรียกจากเธรดหลัก

คุณสามารถเปิดใช้งานThread Sanitizer เพื่อค้นหาบรรทัดที่ไม่เหมาะสม

คุณสามารถใส่บรรทัดที่ไม่เหมาะสมในเธรดหลักได้ดังนี้:

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

อัปเดตแผนที่ Google เวอร์ชันปัจจุบันของคุณด้วย Google Maps ต้องทำการอัปเดตสองสามอย่างสำหรับตัวตรวจสอบเธรด

สำหรับคำถาม: "เหตุใดจึงเกิดขึ้น" ฉันคิดว่า Apple เพิ่มการยืนยันสำหรับกรณีขอบซึ่ง Google ต้องอัปเดตพ็อดสำหรับ


1
@thibautnoah คุณกำลังบอกว่าเพราะฉันไม่ได้แปลว่า "มัน (ปัญหา) เกิดขึ้นเพราะคุณใช้ xcode 9 beta ร่วมกับ API ของ Google" หรือเพราะคุณกำลังเผชิญกับข้อผิดพลาดที่คล้ายกันซึ่งคำตอบของฉันไม่สามารถแก้ไขได้?
ScottyBlades

7
Xcode 9 เน้นย้ำปัญหาเธรดบางอย่างซึ่ง xcode 8 ตรวจไม่พบ (ไม่ว่าจะเกิดจากการตั้งค่า xcode หรือสิ่งอื่นจะถูกกำหนด) การเปลี่ยนกลับไปใช้ xcode 8 นั้นเท่ากับการเพิกเฉยต่อปัญหาเธรดของคุณ แต่ปัญหาเหล่านี้ยังคงอยู่ที่นั่นและไม่ได้รับการแก้ไขดังนั้นจึงไม่ใช่วิธีแก้ปัญหาคุณเพียงแค่ฝังหัวของคุณลงในทรายและแสร้งทำเป็นว่าทุกอย่างเรียบร้อย หากปัญหามาจากกรอบงานโปรดส่งปัญหาเพื่อให้สามารถแก้ไขได้
thibaut noah

Xcode 9 ตรวจพบปัญหาเธรดซึ่ง xcode 8 ไม่ได้สัดส่วนกับการตรวจจับและ Xcode 9 ร่วมกับ API ของ Google อาจทำให้เกิดข้อบกพร่องนี้ จุดบกพร่องนี้อยู่ในโปรแกรมดีบั๊กสำหรับการขัดข้องหลายครั้งและการขัดข้องจะไม่เกิดขึ้นอีกต่อไปเมื่อคุณเปลี่ยนกลับไปใช้ xcode 8
ScottyBlades

คุณประเด็นคือตัวตรวจสอบด้ายกำลังแสดงอาการไม่ใช่สาเหตุ ฉันกำลังบอกว่า Xcode 9 beta เป็นทั้งสาเหตุและตัวสื่อสารอาการ "ข้อขัดข้องจะไม่เกิดขึ้นอีกต่อไปเมื่อคุณเปลี่ยนกลับไปใช้ xcode 8" มีความแตกต่างระหว่างคำเตือน XCode และข้อขัดข้องจริงกับการอ่านค่าดีบักเกอร์ ข้อผิดพลาดนี้อาจแสดงเป็นคำเตือนหรือข้อขัดข้อง การหยุดทำงานจะหายไปโดยสิ้นเชิงเมื่อเปลี่ยนกลับไปใช้ xcode 8 Xcode 9 beta เรียกว่าเบต้าด้วยเหตุผลที่ดี
ScottyBlades

2
ใช่ ... ฉันคิดว่ามันยากสำหรับนักพัฒนา ios หลายคนที่จะเห็นว่าเพียงเพราะมีบางอย่างแสดงอาการไม่ได้หมายความว่าจะไม่เป็นสาเหตุเช่นกัน ฉันคิดว่ามันยากที่จะยอมรับว่า Apple อาจทำผิดพลาด
ScottyBlades

158

ยากที่จะหารหัส UI ที่บางครั้งไม่ได้ดำเนินการในเธรดหลัก คุณสามารถใช้เคล็ดลับด้านล่างเพื่อค้นหาและแก้ไขได้

  1. เลือก Edit Scheme -> Diagnostics ติ๊ก Main Thread Checker

    Xcode 11.4.1

    คลิกลูกศรเล็ก ๆ ถัดจาก Main Thread Checker เพื่อสร้างเบรกพอยต์ Main Thread Checker ป้อนคำอธิบายภาพที่นี่

    Xcode ก่อนหน้า

    ทำเครื่องหมายที่หยุดชั่วคราวสำหรับปัญหา ป้อนคำอธิบายภาพที่นี่

  2. เรียกใช้แอปพลิเคชัน iOS ของคุณเพื่อทำให้เกิดปัญหานี้อีกครั้ง (Xcode ควรหยุดชั่วคราวในฉบับแรก) ป้อนคำอธิบายภาพที่นี่

  3. ตัดโค้ดที่แก้ไข UI ใน DispatchQueue.main.async {} ป้อนคำอธิบายภาพที่นี่


4
ขอบคุณช่วยฉันได้ 30 นาที
Orange

10
ด้วยเหตุผลบางประการเมื่อฉันทำเช่นนั้นใน Xcode 10.1 ฉันได้รับเฉพาะ callstack ที่ทำอะไรไม่ถูกและฉันไม่สามารถเชื่อมโยงกับบรรทัดรหัสได้: 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
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 แก้ไข: ฉันพบลูกศรเล็ก ๆ ถัดจากตัวตรวจสอบเธรดหลัก การคลิกเพื่อเพิ่มเบรกพอยต์สำหรับคุณ
ChrisO

47

ตัดบรรทัดของโค้ดที่แก้ไข UI DispatchQueue.main.async {}เพื่อให้แน่ใจว่ารันบนเธรดหลัก มิฉะนั้นคุณอาจเรียกพวกเขาจากเธรดพื้นหลังซึ่งไม่อนุญาตให้แก้ไข UI บรรทัดของโค้ดดังกล่าวทั้งหมดจะต้องดำเนินการจากเธรดหลัก


4
ใช่ฉันเคยใช้แล้ว แต่ยังคงมีคำเตือนอยู่
MattBlack

@ ปังใช้สำหรับพิมพ์สิ่งต่างๆไม่ใช่สำหรับรหัส UI หลัก
Toma

4
@MattBlack พยายามรวมทุกสิ่งที่ปรับเปลี่ยน UI บนDispatchQueue.main.async {}
Toma

@ user6603599- ทำงานเหมือนมีเสน่ห์
Sree

3

อ้างอิงลิงค์นี้ https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

สำหรับฉันสิ่งนี้ใช้ได้ผลเมื่อฉันโทรจากบล็อก


1
หากคุณใช้ Swift 4+ นี่เป็นทางออกที่ดีที่สุดที่ทำงานได้อย่างสมบูรณ์แบบขอขอบคุณที่ช่วยฉันประหยัดเวลา ฉันเล่นกับ Scheme Editor แล้ว แต่การทำตามคำแนะนำของ Apple เป็นตัวเลือกที่ดีที่สุดในตอนนี้และก้าวไปข้างหน้า
AbuTaareq


-34

เลือกรูปแบบ -> Diagnotics ลบตัวตรวจสอบเธรดหลักจากนั้นคำเตือนจะหายไป โปรแกรมแก้ไขโครงการ


18
ฉันไม่คิดว่านี่เป็นความคิดที่ดี มีปัญหาที่นี่ซึ่งตัวตรวจสอบเธรดได้ค้นพบ การปิดใช้งานตัวตรวจสอบเธรดจะช่วยให้ปัญหานี้และในอนาคตไม่ถูกค้นพบและก่อให้เกิดหนี้ทางเทคนิคในอนาคตเพื่อแก้ไขปัญหา
ablarg

1
จริงๆแล้วประเด็นของฉันคือเราสามารถทำได้เมื่อเราใช้ OpenGL es rendering เพราะเราไม่สามารถแสดงเฟรมบัฟเฟอร์ในเธรดหลักได้ ขวา?
เพ็ง

1
อ๊ะถ้าการทำสงครามไม่ปรากฏปัญหาก็ไม่มี?
turingtested

11
"ทำไมอุปกรณ์ตรวจจับควันของฉันถึงดับอยู่เรื่อย ๆ " "เพียงแค่ถอดแบตเตอรี่ออกแก้ไขปัญหาได้"
John Montgomery

หากคำเตือนไม่ปรากฏปัญหาไม่มีอยู่?
S. Gissel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.