NSDefaultRunLoopMode เทียบกับ NSRunLoopCommonModes


114

เมื่อใดก็ตามที่ฉันพยายามที่จะดาวน์โหลดไฟล์ขนาดใหญ่ที่อยู่เบื้องหลังUIScrollView, MPMapViewหรือสิ่งที่ขั้นตอนการดาวน์โหลดที่ได้รับการหยุดเร็วที่สุดเท่าที่ฉันสัมผัสหน้าจอ iPhone โชคดีที่โพสต์บล็อกที่ยอดเยี่ยมโดยJörnแนะนำตัวเลือกอื่นNSRunLoopCommonModesสำหรับการเชื่อมต่อ

นั่นทำให้ฉันดูรายละเอียดของสองโหมด NSDefaultRunLoopMode และ NSRunLoopCommonModes แต่เอกสารของ Apple ไม่ได้อธิบายอย่างกรุณานอกเหนือจากการพูด

NSDefaultRunLoopMode

โหมดจัดการกับแหล่งอินพุตอื่นที่ไม่ใช่อ็อบเจ็กต์ NSConnection นี่คือโหมดรันลูปที่ใช้บ่อยที่สุด

NSRunLoopCommonModes

อ็อบเจ็กต์ที่เพิ่มเข้าในรันลูปโดยใช้ค่านี้เนื่องจากโหมดถูกมอนิเตอร์โดยโหมดรันลูปทั้งหมดที่ได้รับการประกาศให้เป็นสมาชิกของชุดโหมด "ทั่วไป" ดูคำอธิบายของ CFRunLoopAddCommonMode สำหรับรายละเอียด

CFRunLoopAddCommonMode

แหล่งที่มาตัวจับเวลาและผู้สังเกตการณ์จะได้รับการลงทะเบียนในโหมดรันลูปตั้งแต่หนึ่งโหมดขึ้นไปและจะรันก็ต่อเมื่อรันลูปทำงานในโหมดใดโหมดหนึ่งเท่านั้น โหมดทั่วไปคือชุดของโหมดวนรอบการทำงานที่คุณสามารถกำหนดชุดของแหล่งที่มาตัวจับเวลาและผู้สังเกตการณ์ที่แบ่งใช้โดยโหมดเหล่านี้ ตัวอย่างเช่นแทนที่จะลงทะเบียนซอร์สในโหมด run loop แต่ละโหมดคุณสามารถลงทะเบียนครั้งเดียวกับโหมดหลอกทั่วไปของ run loop และจะถูกลงทะเบียนโดยอัตโนมัติในโหมด run loop แต่ละโหมดในชุดโหมดทั่วไป ในทำนองเดียวกันเมื่อเพิ่มโหมดลงในชุดของโหมดทั่วไปแหล่งที่มาตัวจับเวลาหรือผู้สังเกตการณ์ที่ลงทะเบียนไว้แล้วในโหมดหลอกทั่วไปจะถูกเพิ่มลงในโหมดทั่วไปที่เพิ่มใหม่

ใครช่วยอธิบายทั้งสองเป็นภาษามนุษย์ได้ไหม

คำตอบ:


204

รันลูปเป็นกลไกที่ช่วยให้ระบบสามารถปลุกเธรดสลีปเพื่อให้จัดการเหตุการณ์แบบอะซิงโครนัสได้ โดยปกติเมื่อคุณรันเธรด (ยกเว้นเธรดหลัก) มีตัวเลือกในการเริ่มเธรดในการรันลูปหรือไม่ หากเธรดรันการเรียงลำดับหรือการดำเนินการที่รันเป็นเวลานานโดยไม่มีการโต้ตอบกับเหตุการณ์ภายนอกและไม่มีตัวจับเวลาคุณไม่จำเป็นต้องรันลูป แต่ถ้าเธรดของคุณต้องตอบสนองต่อเหตุการณ์ที่เข้ามาควรแนบกับรันลูปเพื่อ ปลุกเธรดเมื่อมีกิจกรรมใหม่มาถึง นี่เป็นกรณีของNSURLConnectionเธรดที่สร้างขึ้นเนื่องจากจะปลุกเฉพาะเหตุการณ์ที่เข้ามา (จากเครือข่าย)

แต่ละเธรดสามารถเชื่อมโยงกับการทำงานหลายลูปหรือสามารถเชื่อมโยงกับลูปการรันเฉพาะที่สามารถตั้งค่าให้ทำงานในโหมดต่างๆ "โหมดวนรอบการทำงาน" เป็นแบบแผนที่ระบบปฏิบัติการใช้เพื่อกำหนดกฎเกณฑ์บางประการสำหรับเวลาที่จะส่งเหตุการณ์บางอย่างหรือรวบรวมเพื่อจัดส่งในภายหลัง

โดยปกติแล้วการวนรอบการทำงานทั้งหมดจะถูกตั้งค่าเป็น "โหมดเริ่มต้น" ซึ่งสร้างวิธีเริ่มต้นในการจัดการเหตุการณ์อินพุต ตัวอย่างเช่นทันทีที่เหตุการณ์การลากเมาส์ (Mac OS) หรือการสัมผัส (บน iOS) เกิดขึ้นโหมดสำหรับการวนรอบการทำงานนี้จะถูกตั้งค่าเป็นการติดตามเหตุการณ์ ซึ่งหมายความว่าเธรดจะไม่ถูกปลุกในเหตุการณ์เครือข่ายใหม่ แต่เหตุการณ์เหล่านี้จะถูกส่งในภายหลังเมื่อเหตุการณ์การป้อนข้อมูลของผู้ใช้สิ้นสุดลงและการวนรอบการทำงานจะถูกตั้งค่าเป็นโหมดเริ่มต้นอีกครั้ง เห็นได้ชัดว่านี่เป็นทางเลือกที่สถาปนิกระบบปฏิบัติการทำขึ้นเพื่อให้ความสำคัญกับเหตุการณ์ของผู้ใช้แทนที่จะเป็นเหตุการณ์พื้นหลัง

หากคุณตัดสินใจที่จะเปลี่ยนโหมดรันลูปสำหรับNSURLConnectionเธรดของคุณโดยใช้scheduleInRunLoop:forModes:คุณสามารถกำหนดเธรดเป็นโหมดรันลูปพิเศษแทนที่จะเป็นรันลูปเริ่มต้นเฉพาะ โหมดหลอกพิเศษที่เรียกว่าNSRunLoopCommonModesถูกใช้โดยแหล่งอินพุตจำนวนมากรวมถึงการติดตามเหตุการณ์ ตัวอย่างเช่นการกำหนดNSURLConnectionอินสแตนซ์ให้กับโหมดทั่วไปหมายถึงการเชื่อมโยงเหตุการณ์กับ "โหมดการติดตาม" นอกเหนือจาก "โหมดเริ่มต้น" ข้อดี / ข้อเสียอย่างหนึ่งของการเชื่อมโยงเธรดด้วยNSRunLoopCommonModesคือเธรดจะไม่ถูกบล็อกโดยเหตุการณ์การสัมผัส

โหมดใหม่สามารถเพิ่มลงในโหมดทั่วไปได้ แต่นี่เป็นการทำงานระดับต่ำ

ฉันต้องการปิดโดยเพิ่มบันทึกบางส่วน:

  • โดยปกติเราต้องใช้ชุดรูปภาพหรือภาพขนาดย่อที่ดาวน์โหลดจากเครือข่ายด้วยมุมมองตาราง เราอาจคิดว่าการดาวน์โหลดภาพเหล่านี้จากเครือข่ายในขณะที่มุมมองตารางกำลังเลื่อนสามารถปรับปรุงประสบการณ์ของผู้ใช้ได้ (เนื่องจากเราสามารถเห็นภาพขณะเลื่อน) แต่สิ่งนี้ไม่เป็นประโยชน์เนื่องจากความลื่นไหลของการเลื่อนอาจได้รับผลกระทบอย่างมาก ในตัวอย่างนี้NSURLConnectionไม่ควรใช้ run loop จะเป็นการดีกว่าถ้าใช้UIScrollViewวิธีการมอบหมายเพื่อตรวจจับเมื่อการเลื่อนสิ้นสุดลงจากนั้นอัปเดตตารางและดาวน์โหลดรายการใหม่จากเครือข่าย

  • คุณอาจพิจารณาใช้ GCD ซึ่งจะช่วยคุณในการ "ป้องกัน" โค้ดของคุณจากปัญหาการจัดการลูป ในตัวอย่างข้างต้นคุณอาจพิจารณาเพิ่มคำขอเครือข่ายของคุณในคิวอนุกรมที่กำหนดเอง


9
เรียนคุณ Viggio24 ขอบคุณมากสำหรับคำอธิบายที่ชัดเจนและแม่นยำนี้ ฉันจะขอให้ Apple รวมความคิดเห็นของคุณไว้ในคู่มือ API ;)
Stkim1

7
คำตอบของviggio24สมบูรณ์แบบ สำหรับผู้ที่สนใจฉันจะชี้ให้เห็นว่าเซสชัน 208 (แอพเครือข่ายสำหรับ iPhone OS ตอนที่ 2)จาก WWDC 2010 มีบทนำเกี่ยวกับลูปการทำงาน หากคุณสนใจลองดู หวังว่าจะช่วยได้
Lorenzo B

19
เพียงแค่ทราบสำหรับตัวเอง: ช่วยให้เหตุการณ์จับเวลาในขณะที่เลื่อนNSRunLoopCommonModes ป้องกันตัวจับเวลาขณะเลื่อน UIScrollViewNSDefaultRunLoopMode
eonil

2
ฉันพบว่าความคิดเห็นเกี่ยวกับการอัปเดตมุมมองแบบเลื่อนนั้นน่าสนใจมากเนื่องจากกล่าวถึงหัวข้อที่ท้าทายมาก เพียงเพื่อเพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งนี้: เมื่อคุณตั้งค่าโหมดสำหรับการเชื่อมต่อ NSURLC สิ่งนี้จะส่งผลต่อการเรียกใช้การโทรกลับของผู้รับมอบสิทธิ์เท่านั้น ฉันเข้าใจว่าการอัปเดต scrollView ที่นี่อาจส่งผลให้เกิดปัญหาด้านประสิทธิภาพ แต่เหตุใดจึงเกิดขึ้น หากคำตอบคือต้องโหลดรูปภาพลงในหน่วยความจำคุณสามารถทำได้โดยการเขียนลงในบริบทกราฟิกบนพื้นหลังและอัปเดตเลเยอร์เธรดหลักของมุมมองของคุณหลังจากทำสิ่งนี้ ฟังดูสมเหตุสมผลไหม
nebillo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.