เพื่อ drawRect หรือไม่เพื่อ drawRect (เมื่อหนึ่งควรใช้ drawRect / Core Graphics vs subviews / images และทำไม?)


142

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

ฉันเข้าใจเช่นกันว่ามันไม่สมเหตุสมผลที่จะปรับให้เหมาะสมล่วงหน้าและทำบางสิ่งที่ยากกว่าก่อนที่จะทำการทำโปรไฟล์ พิจารณาว่าฉันพอใจกับทั้งสองวิธีและตอนนี้ต้องการความเข้าใจที่ลึกซึ้งยิ่งขึ้น

ความสับสนมากมายของฉันมาจากการเรียนรู้วิธีทำให้ประสิทธิภาพการเลื่อนดูตารางอย่างราบรื่นและรวดเร็ว แน่นอนแหล่งที่มาดั้งเดิมของวิธีนี้มาจากผู้เขียนที่อยู่เบื้องหลังตัวสั่นด้วยความตื่นเต้นสำหรับ iPhone (tweetie เดิม) โดยพื้นฐานแล้วจะบอกว่าเพื่อให้การเลื่อนตารางเนยเป็นไปอย่างราบรื่นความลับคือไม่ต้องใช้การดูย่อย แต่แทนที่จะวาดทั้งหมดใน uiview ที่กำหนดเอง โดยพื้นฐานแล้วดูเหมือนว่าการใช้การดูย่อยจำนวนมากจะทำให้การเรนเดอร์ช้าลงเพราะพวกเขามีค่าใช้จ่ายจำนวนมาก

เพื่อความเป็นธรรมนี้ถูกเขียนขึ้นเมื่อ 3GS เป็นแบรนด์ที่ค่อนข้างใหม่ spankin และ iDevices ได้รับเร็วขึ้นมากตั้งแต่นั้นมา ยังคงใช้วิธีนี้เป็นประจำ แนะนำในinterwebsและที่อื่น ๆ สำหรับตารางที่มีประสิทธิภาพสูง ในความเป็นจริงมันเป็นวิธีการที่แนะนำไว้ในตารางที่แอปเปิ้ลโค้ดตัวอย่างได้รับการแนะนำในวิดีโอ WWDC หลายคน ( ถอนเงินปฏิบัติสำหรับ iOS นักพัฒนา ) และ iOS หลายโปรแกรมหนังสือ

มีเครื่องมือที่ดูยอดเยี่ยมในการออกแบบกราฟิกและสร้างรหัส Core Graphics สำหรับพวกเขา

ดังนั้นในตอนแรกฉันจึงเชื่อว่า "มีเหตุผลที่ทำให้ Core Graphics มีอยู่มันเร็วมาก"

แต่ทันทีที่ฉันคิดว่าฉันได้รับแนวคิด "โปรดปรานกราฟิกหลักเมื่อเป็นไปได้" ฉันเริ่มเห็นว่า drawRect มักจะรับผิดชอบต่อการตอบสนองที่ไม่ดีในแอปหนึ่งคือหน่วยความจำที่ชาญฉลาดและมีราคาแพงมาก โดยพื้นฐานแล้วฉันควร " หลีกเลี่ยงการเอาชนะ drawRect " ( ประสิทธิภาพของแอพ iOS WWDC 2012 : กราฟิกและภาพเคลื่อนไหว )

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

ฉันเห็นสถานการณ์ที่ชัดเจนในการใช้ Core Graphics:

  1. คุณมีข้อมูลแบบไดนามิก (ตัวอย่างแผนภูมิหุ้นของ Apple)
  2. คุณมีองค์ประกอบ UI ที่ยืดหยุ่นที่ไม่สามารถดำเนินการได้ด้วยภาพที่ปรับขนาดได้ง่าย
  3. คุณกำลังสร้างกราฟิกแบบไดนามิกซึ่งเมื่อใช้การแสดงผลหลายแห่ง

ฉันเห็นสถานการณ์เพื่อหลีกเลี่ยง Core Graphics:

  1. คุณสมบัติของมุมมองของคุณจะต้องมีการเคลื่อนไหวแยกต่างหาก
  2. คุณมีลำดับชั้นการดูค่อนข้างเล็กดังนั้นการรับรู้ถึงความพยายามพิเศษในการใช้ CG จึงไม่คุ้มค่าที่จะได้รับ
  3. คุณต้องการอัปเดตชิ้นส่วนของมุมมองโดยไม่ต้องเขียนใหม่ทั้งหมด
  4. โครงร่างของการชมย่อยของคุณจำเป็นต้องอัปเดตเมื่อขนาดมุมมองพาเรนต์เปลี่ยนไป

มอบความรู้ของคุณ ในสถานการณ์ใดบ้างที่คุณเข้าถึงสำหรับ drawRect / Core Graphics (ที่สามารถทำได้ด้วยการดูย่อย) ปัจจัยอะไรที่ทำให้คุณตัดสินใจเช่นนั้น? วิธีการ / ทำไมการวาดภาพในมุมมองที่กำหนดเองหนึ่งแนะนำสำหรับการเลื่อนเซลล์ตารางอย่างราบรื่น buttery แต่ Apple แนะนำให้ drawRect กับเหตุผลด้านประสิทธิภาพโดยทั่วไป? ภาพพื้นหลังแบบไหนที่เกี่ยวกับ (เมื่อคุณสร้างด้วย CG กับการใช้ภาพ png ที่ปรับขนาดได้)

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

อัปเดตคำถาม

ขอบคุณสำหรับข้อมูลที่ทุกคน บางคำถามที่ชัดเจนที่นี่:

  1. หากคุณกำลังวาดสิ่งที่มีกราฟิกหลัก แต่สามารถทำสิ่งเดียวกันกับ UIImageViews และ png ที่แสดงผลล่วงหน้าคุณควรไปเส้นทางนั้นเสมอหรือไม่
  2. คำถามที่คล้ายกัน: โดยเฉพาะอย่างยิ่งกับเครื่องมือ badass เช่นนี้คุณควรพิจารณาการวาดองค์ประกอบอินเทอร์เฟซในกราฟิกหลักเมื่อใด (อาจเป็นได้เมื่อการแสดงองค์ประกอบของคุณเป็นตัวแปรเช่นปุ่มที่มีการเปลี่ยนแปลงสี 20 แบบกรณีอื่น ๆ ?)
  3. ด้วยความเข้าใจของฉันในคำตอบของฉันด้านล่างประสิทธิภาพการทำงานแบบเดียวกันสำหรับเซลล์ตารางอาจได้รับจากการจับภาพบิตแมปสแน็ปช็อตของเซลล์ของคุณอย่างมีประสิทธิภาพหลังจาก UIView ที่ซับซ้อนของคุณทำการเรนเดอร์เอง เห็นได้ชัดว่าบางชิ้นจะต้องมีการออกกำลังกาย แค่ความคิดที่น่าสนใจที่ฉันมี

คำตอบ:


72

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

เวิร์กโฟลว์ทั่วไปควรสร้างภาพรวมของตารางพร้อมกับหัวข้อย่อย ใช้เครื่องมือเพื่อวัดอัตราเฟรมบนฮาร์ดแวร์ที่เก่าที่สุดที่แอพของคุณรองรับ หากคุณไม่สามารถรับ 60fps ได้ให้เลื่อนลงไปที่ CoreGraphics เมื่อคุณทำสิ่งนี้มาระยะหนึ่งคุณจะรู้สึกว่า UIKit น่าจะเสียเวลา

ดังนั้นทำไมคอร์กราฟิกส์จึงเร็ว?

CoreGraphics ไม่เร็วอย่างแท้จริง ถ้ามันถูกใช้ตลอดเวลาคุณอาจจะช้า มันเป็น API การวาดที่สมบูรณ์ซึ่งต้องการงานที่ต้องทำบน CPU ซึ่งตรงข้ามกับงาน UIKit จำนวนมากที่ถูกบรรจุลงใน GPU หากคุณต้องทำให้ลูกเคลื่อนไหวผ่านหน้าจอมันจะเป็นความคิดที่แย่มากที่จะเรียก setNeedsDisplay ในมุมมอง 60 ครั้งต่อวินาที ดังนั้นหากคุณมีองค์ประกอบย่อยของมุมมองของคุณที่จำเป็นต้องเคลื่อนไหวเป็นรายบุคคลแต่ละองค์ประกอบควรเป็นเลเยอร์แยกต่างหาก

ปัญหาอื่นคือเมื่อคุณไม่ได้วาดรูปแบบกำหนดเองด้วย drawRect UIKit สามารถปรับมุมมองสต็อกให้เหมาะสมดังนั้น drawRect เป็นแบบไม่ใช้งานหรืออาจใช้ทางลัดในการเรียงแบบ เมื่อคุณแทนที่ drawRect UIKit จะต้องใช้เส้นทางที่ช้าเพราะมันไม่รู้ว่าคุณกำลังทำอะไรอยู่

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

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


53

ความแตกต่างคือ UIView และ CALayer เป็นหลักในการจัดการกับภาพคงที่ ภาพเหล่านี้ถูกอัปโหลดไปยังการ์ดกราฟิก (หากคุณรู้จัก OpenGL ให้นึกถึงภาพเป็นพื้นผิวและ UIView / CALayer เป็นรูปหลายเหลี่ยมที่แสดงพื้นผิวดังกล่าว) เมื่อภาพอยู่บน GPU มันสามารถวาดได้อย่างรวดเร็วและหลายครั้งและ (มีโทษประสิทธิภาพเล็กน้อย) แม้จะมีระดับความโปร่งใสอัลฟาในระดับต่าง ๆ ที่ด้านบนของภาพอื่น ๆ

CoreGraphics / Quartz เป็น API สำหรับการสร้างภาพ มันต้องใช้บัฟเฟอร์พิกเซล (อีกครั้งคิดว่าพื้นผิว OpenGL) และเปลี่ยนพิกเซลแต่ละตัวภายใน ทั้งหมดนี้เกิดขึ้นใน RAM และบน CPU และเมื่อมีการสร้าง Quartz ครั้งเดียวภาพจะได้รับ "แดง" กลับสู่ GPU การปัดเศษของการรับภาพจาก GPU เปลี่ยนไปจากนั้นอัปโหลดภาพทั้งหมด (หรืออย่างน้อยก้อนที่ค่อนข้างใหญ่) กลับสู่ GPU ค่อนข้างช้า ยิ่งไปกว่านั้นการวาดภาพควอทซ์ที่เกิดขึ้นจริงในขณะที่ทำสิ่งที่คุณกำลังทำอย่างรวดเร็วนั้นช้ากว่าสิ่งที่ GPU ทำ

เห็นได้ชัดว่าการพิจารณา GPU ส่วนใหญ่เคลื่อนที่ไปรอบ ๆ พิกเซลที่ไม่เปลี่ยนแปลงในกลุ่มก้อนใหญ่ Quartz จะเข้าถึงพิกเซลแบบสุ่มและแชร์ CPU กับระบบเครือข่ายเสียง ฯลฯ นอกจากนี้หากคุณมีองค์ประกอบหลายอย่างที่คุณวาดโดยใช้ Quartz ในเวลาเดียวกันคุณจะต้องวาดทั้งหมดอีกครั้งเมื่อมีการเปลี่ยนแปลงจากนั้นอัปโหลด ชิ้นส่วนทั้งหมดแม้ว่าคุณจะเปลี่ยนภาพหนึ่งภาพแล้วปล่อยให้ UIViews หรือ CALayers วางลงบนภาพอื่น ๆ ของคุณคุณสามารถหนีไปได้ด้วยการอัปโหลดข้อมูลจำนวนน้อยลงไปยัง GPU

เมื่อคุณไม่ใช้ -drawRect :, การดูส่วนใหญ่สามารถปรับให้เหมาะสม พวกเขาไม่มีพิกเซลใด ๆ ดังนั้นจึงไม่สามารถวาดอะไรได้ มุมมองอื่น ๆ เช่น UIImageView เพียงวาด UIImage เท่านั้น (ซึ่งอีกครั้งเป็นการอ้างอิงถึงพื้นผิวซึ่งอาจถูกโหลดลงบน GPU แล้ว) ดังนั้นหากคุณวาด UIImage เดียวกัน 5 ครั้งโดยใช้ UIImageView มันจะถูกอัปโหลดไปยัง GPU เพียงครั้งเดียวแล้วดึงไปยังจอแสดงผลใน 5 ตำแหน่งที่ต่างกันประหยัดเวลาและ CPU ของเรา

เมื่อคุณใช้ -drawRect: นี่จะทำให้รูปภาพใหม่ถูกสร้างขึ้น จากนั้นคุณวาดลงบนสิ่งนั้นบน CPU โดยใช้ควอตซ์ หากคุณวาด UII ใน mageRect ของคุณอาจเป็นไปได้ว่าจะดาวน์โหลดภาพจาก GPU คัดลอกลงในภาพที่คุณวาดไปและเมื่อเสร็จแล้วให้อัปโหลดสำเนาที่สองของภาพนี้กลับไปที่การ์ดกราฟิก ดังนั้นคุณจึงใช้หน่วยความจำ GPU สองเท่าในอุปกรณ์

ดังนั้นวิธีที่เร็วที่สุดในการวาดมักจะแยกเนื้อหาแบบสแตติกออกจากการเปลี่ยนแปลงเนื้อหา (ใน UIViews / UIView subclasses / CALayers แยกต่างหาก) โหลดเนื้อหาสแตติกเป็น UIImage และวาดโดยใช้ UIImageView และวางเนื้อหาที่สร้างแบบไดนามิกที่รันไทม์ใน drawRect หากคุณมีเนื้อหาที่ถูกวาดซ้ำ ๆ แต่โดยตัวมันเองจะไม่เปลี่ยนแปลง (เช่น 3 ไอคอนที่แสดงในช่องเดียวกันเพื่อระบุสถานะ) ใช้ UIImageView เช่นกัน

ข้อแม้หนึ่ง: มีสิ่งต่าง ๆ เช่นมี UIV วิวมากเกินไป พื้นที่ที่มีความโปร่งใสโดยเฉพาะอย่างยิ่งใช้เวลาในการวาด GPU ที่ใหญ่กว่าเนื่องจากพวกเขาจำเป็นต้องผสมกับพิกเซลอื่น ๆ ที่อยู่ด้านหลังเมื่อแสดง นี่คือเหตุผลที่คุณสามารถทำเครื่องหมาย UIView ว่า "ทึบแสง" เพื่อระบุถึง GPU ว่าสามารถกำจัดทุกอย่างที่อยู่ด้านหลังภาพได้

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


ขอบคุณสำหรับคำตอบโดยละเอียด หวังว่าผู้คนจำนวนมากจะเลื่อนลงมาและโหวตสิ่งนี้เช่นกัน
Bob Spryn

หวังว่าฉันจะสามารถโหวตได้สองครั้ง ขอบคุณสำหรับการเขียนที่ยอดเยี่ยม!
ชายฝั่งทะเลของทิเบต

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

@ ผู้เห็นเหตุการณ์ฉันได้รับคำตอบของคุณและคุณพูดถึงการทำเครื่องหมายวัตถุเป็น "ทึบแสงลบล้างทุกอย่างที่อยู่เบื้องหลังภาพนั้น" คุณช่วยส่องแสงในส่วนนั้นได้ไหม
Rikh

@Rikh การทำเครื่องหมายเลเยอร์เป็นทึบแสงหมายความว่า a) ในกรณีส่วนใหญ่ GPU จะไม่รบกวนการวาดเลเยอร์อื่น ๆ ภายใต้เลเยอร์นั้นดีอย่างน้อยก็ส่วนของพวกเขาที่อยู่ภายใต้เลเยอร์ทึบแสง แม้ว่าพวกเขาจะถูกวาดมันจะไม่ทำการผสมอัลฟา แต่จะคัดลอกเนื้อหาของเลเยอร์บนสุดบนหน้าจอ (โดยปกติแล้วพิกเซลที่โปร่งใสอย่างเต็มรูปแบบในเลเยอร์ทึบแสงจะกลายเป็นสีดำหรืออย่างน้อยก็เป็นสีทึบรุ่น)
uliwitness

26

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

วิธีการทั่วไป

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

ทำไม

  1. มีสองคอขวดหลักที่เป็นไปได้ใน iDevice, CPU และ GPU
  2. ซีพียูมีหน้าที่รับผิดชอบในการวาดภาพ / การเรนเดอร์เริ่มต้นของมุมมอง
  3. GPU รับผิดชอบส่วนใหญ่ของแอนิเมชัน (Core Animation), เอฟเฟกต์เลเยอร์, ​​การจัดองค์ประกอบภาพ ฯลฯ
  4. UIView มีการปรับแต่งแคชจำนวนมากและสร้างขึ้นเพื่อจัดการลำดับชั้นมุมมองที่ซับซ้อน
  5. เมื่อคุณเอาชนะ drawRect คุณจะพลาดประโยชน์มากมายที่ UIView มอบให้และโดยทั่วไปแล้วช้ากว่าการปล่อยให้ UIView จัดการกับการเรนเดอร์

การวาดเนื้อหาเซลล์ใน UIView แบบแฟลตเดียวสามารถปรับปรุง FPS ของคุณได้อย่างมากในตารางเลื่อน

อย่างที่ฉันได้กล่าวไว้ข้างต้น CPU และ GPU เป็นคอขวดที่เป็นไปได้สองอย่าง เนื่องจากโดยทั่วไปแล้วพวกเขาจัดการกับสิ่งต่าง ๆ คุณต้องใส่ใจกับปัญหาคอขวดที่คุณใช้ ในกรณีของการเลื่อนตารางไม่ใช่ว่า Core Graphics จะวาดเร็วขึ้นและนั่นเป็นสาเหตุที่มันสามารถปรับปรุง FPS ของคุณได้อย่างมาก

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

เหตุใดการเอาชนะ drawRect (โดยใช้กราฟิกหลัก) สามารถช่วยให้การเลื่อนตาราง:

จากสิ่งที่ฉันเข้าใจ GPU ไม่รับผิดชอบต่อการเรนเดอร์เริ่มต้นของมุมมอง แต่เป็นพื้นผิวที่ส่งมอบแทนหรือบิตแมปแทนบางครั้งก็มีคุณสมบัติเลเยอร์บางอย่างหลังจากที่พวกเขาได้รับการแสดงผล จากนั้นจะรับผิดชอบในการคอมโพสิตบิตแมปการแสดงเลเยอร์เหล่านั้นทั้งหมดส่งผลกระทบต่อและภาพเคลื่อนไหวส่วนใหญ่ (Core Animation)

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

ดังนั้นโดยสรุปเหตุผลที่การวาดเซลล์ของคุณในมุมมองเดียวด้วยกราฟิกหลักสามารถเพิ่มความเร็วในการเลื่อนตารางของคุณไม่ใช่เพราะมันวาดได้เร็วขึ้น แต่เพราะมันลดภาระของ GPU ซึ่งเป็นปัญหาคอขวดที่ทำให้คุณเดือดร้อนในสถานการณ์นั้น ๆ .


1
แม้ว่าระวัง GPUs ประกอบโครงสร้างเลเยอร์ใหม่ทั้งหมดสำหรับแต่ละเฟรมอย่างมีประสิทธิภาพ ดังนั้นการย้ายเลเยอร์จึงไม่มีต้นทุนอย่างมีประสิทธิภาพ หากคุณสร้างเลเยอร์ใหญ่หนึ่งการย้ายที่เลเยอร์หนึ่งนั้นเร็วกว่าการย้ายหลายเลเยอร์ การย้ายบางสิ่งภายในเลเยอร์นี้เกี่ยวข้องกับ CPU และมีค่าใช้จ่าย เนื่องจากเนื้อหาของเซลล์มักจะไม่เปลี่ยนแปลงมากนัก (เฉพาะการตอบสนองต่อการกระทำของผู้ใช้ที่ไม่ค่อยพบ) การใช้จำนวนการดูที่น้อยลงจะช่วยเร่งความเร็วให้มากขึ้น แต่การสร้างมุมมองขนาดใหญ่เพียงครั้งเดียวพร้อมเซลล์ทั้งหมดจะเป็น Bad Idea ™
uliwitness

6

ฉันเป็นผู้พัฒนาเกมและฉันถามคำถามเดียวกันเมื่อเพื่อนของฉันบอกฉันว่าลำดับชั้นการดูแบบ UIImageView ของฉันกำลังจะทำให้เกมของฉันช้าลงและทำให้เกมแย่ลง จากนั้นฉันก็ทำการค้นคว้าทุกอย่างที่ฉันสามารถหาได้เกี่ยวกับการใช้ UIViews, CoreGraphics, OpenGL หรือบุคคลที่สามอย่าง Cocos2D คำตอบที่สอดคล้องกันที่ผมได้จากเพื่อนครูและวิศวกรแอปเปิ้ลที่ WWDC คือการที่มีจะไม่แตกต่างกันมากในท้ายที่สุดเพราะที่บางระดับพวกเขาทั้งหมดทำในสิ่งเดียวกัน ตัวเลือกระดับสูงกว่าเช่น UIViews ใช้ตัวเลือกระดับล่างเช่น CoreGraphics และ OpenGL เพียงแค่มีการห่อหุ้มโค้ดเพื่อให้ง่ายต่อการใช้งาน

อย่าใช้ CoreGraphics หากคุณเพิ่งจะจบการเขียน UIView อีกครั้ง อย่างไรก็ตามคุณสามารถเพิ่มความเร็วจากการใช้ CoreGraphics ตราบใดที่คุณวาดรูปทั้งหมดในมุมมองเดียว แต่มันคุ้มหรือไม่ คำตอบที่ฉันพบมักไม่มี เมื่อฉันเริ่มเกมครั้งแรกฉันทำงานกับ iPhone 3G เมื่อเกมของฉันซับซ้อนมากขึ้นฉันเริ่มเห็นความล่าช้าบ้าง แต่ด้วยอุปกรณ์รุ่นใหม่มันไม่สามารถสังเกตได้อย่างสมบูรณ์ ตอนนี้ฉันมีแอ็คชั่นมากมายและความล่าช้าเพียงอย่างเดียวดูเหมือนว่าจะลดลง 1-3 fps เมื่อเล่นในระดับที่ซับซ้อนที่สุดใน iPhone 4

ฉันยังตัดสินใจใช้เครื่องมือเพื่อค้นหาฟังก์ชั่นที่ใช้เวลาส่วนใหญ่ ฉันพบว่าปัญหาไม่เกี่ยวข้องกับการใช้ UIViews ของฉัน แทนที่จะเรียกใช้ CGRectMake แทนการคำนวณการชนกันของข้อมูลและการโหลดรูปภาพและไฟล์เสียงแยกต่างหากสำหรับคลาสบางคลาสที่ใช้รูปภาพเดียวกันแทนที่จะให้พวกมันดึงมาจากคลาสหน่วยเก็บข้อมูลส่วนกลางเดียว

ดังนั้นในที่สุดคุณอาจได้รับผลตอบแทนเล็กน้อยจากการใช้ CoreGraphics แต่โดยปกติแล้วจะไม่คุ้มค่าหรืออาจไม่มีผลกระทบใด ๆ เลย ครั้งเดียวที่ฉันใช้ CoreGraphics คือเมื่อวาดรูปทรงเรขาคณิตมากกว่าข้อความและรูปภาพ


8
ฉันคิดว่าคุณอาจทำให้ Core Animation สับสนกับ Core Graphics คอร์กราฟิกส์ช้ามาก ๆ การวาดด้วยซอฟท์แวร์และไม่ได้ใช้สำหรับการวาด UIViews ปกติเว้นแต่คุณจะแทนที่เมธอด drawRect Core Animation เป็นฮาร์ดแวร์ที่เร่งความเร็วรวดเร็วและรับผิดชอบต่อสิ่งที่คุณเห็นบนหน้าจอส่วนใหญ่
Nick Lockwood
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.