เคล็ดลับประสิทธิภาพของ iOS เพื่อให้แอปของคุณมีประสิทธิภาพมากขึ้น
เผยแพร่แล้ว: 2022-03-10แม้ว่าฮาร์ดแวร์ iOS สมัยใหม่จะมีประสิทธิภาพเพียงพอที่จะจัดการกับงานที่ซับซ้อนและซับซ้อนได้หลายอย่าง แต่อุปกรณ์อาจยังคงรู้สึกไม่ตอบสนองหากคุณไม่ระมัดระวังเกี่ยวกับประสิทธิภาพของแอป ในบทความนี้ เราจะพิจารณาเคล็ดลับการเพิ่มประสิทธิภาพห้าประการที่จะทำให้แอปของคุณตอบสนองได้ดีขึ้น
1. Dequeue เซลล์ที่ใช้ซ้ำได้
คุณอาจเคยใช้ tableView.dequeueReusableCell(withIdentifier:for:)
ภายใน tableView(_:cellForRowAt:)
มาก่อน เคยสงสัยไหมว่าทำไมคุณต้องทำตาม API ที่น่าอึดอัดใจนี้ แทนที่จะส่งผ่านอาร์เรย์ของเซลล์เข้าไป? มาดูเหตุผลของเรื่องนี้กัน
สมมติว่าคุณมีมุมมองตารางที่มีหนึ่งพันแถว หากไม่ใช้เซลล์ที่นำกลับมาใช้ใหม่ได้ เราจะต้องสร้างเซลล์ใหม่สำหรับแต่ละแถวดังนี้
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Create a new cell whenever cellForRowAt is called. let cell = UITableViewCell() cell.textLabel?.text = "Cell \(indexPath.row)" return cell }
อย่างที่คุณอาจคิดไว้ วิธีนี้จะเพิ่มเซลล์นับพันเซลล์ลงในหน่วยความจำของอุปกรณ์เมื่อคุณเลื่อนลงมาด้านล่าง ลองนึกภาพว่าจะเกิดอะไรขึ้นหากแต่ละเซลล์มี UIImageView
และข้อความจำนวนมาก: การโหลดทั้งหมดพร้อมกันอาจทำให้แอปมีหน่วยความจำไม่เพียงพอ! นอกจากนั้น ทุกเซลล์จะต้องมีการจัดสรรหน่วยความจำใหม่ในระหว่างการเลื่อน หากคุณเลื่อนมุมมองตารางอย่างรวดเร็ว หน่วยความจำขนาดเล็กจำนวนมากจะถูกจัดสรรทันที และกระบวนการนี้จะทำให้ UI แย่!
ในการแก้ไขปัญหานี้ Apple ได้จัดเตรียม dequeueReusableCell(withIdentifier:for:)
ให้กับเรา การใช้เซลล์ซ้ำทำงานโดยการวางเซลล์ที่ไม่ปรากฏบนหน้าจออีกต่อไปในคิว และเมื่อเซลล์ใหม่กำลังจะปรากฏบนหน้าจอ (เช่น เซลล์ที่ตามมาด้านล่างเมื่อผู้ใช้เลื่อนลง) มุมมองตารางจะ ดึงเซลล์จากคิวนี้และแก้ไขใน cellForRowAt indexPath:
เมธอด
ด้วยการใช้คิวในการจัดเก็บเซลล์ มุมมองตารางจึงไม่จำเป็นต้องสร้างเซลล์เป็นพันเซลล์ แต่ต้องการเซลล์เพียงพอที่จะครอบคลุมพื้นที่ของมุมมองตารางแทน
ด้วยการใช้ dequeueReusableCell
เราสามารถลดหน่วยความจำที่แอพใช้และทำให้หน่วยความจำหมดน้อยลง!
2. การใช้หน้าจอเปิดที่ดูเหมือนหน้าจอเริ่มต้น
ตามที่กล่าวไว้ใน Human Interface Guidelines (HIG) ของ Apple หน้าจอเปิดสามารถใช้เพื่อปรับปรุงการรับรู้ของการตอบสนองของแอพ:
“มีจุดประสงค์เพื่อเพิ่มการรับรู้ของแอปของคุณให้เปิดใช้งานได้อย่างรวดเร็วและพร้อมใช้งานทันที ทุกแอปต้องมีหน้าจอเริ่มต้น”
เป็นเรื่องปกติที่จะใช้หน้าจอเริ่มต้นเป็นหน้าจอเริ่มต้นเพื่อแสดงการสร้างแบรนด์หรือเพื่อเพิ่มแอนิเมชั่นการโหลด ออกแบบหน้าจอเริ่มต้นให้เหมือนกับหน้าจอแรกของแอพของคุณ ตามที่ Apple กล่าวไว้:
“ออกแบบหน้าจอเปิดตัวที่เกือบจะเหมือนกับหน้าจอแรกของแอปของคุณ หากคุณใส่องค์ประกอบที่ดูแตกต่างออกไปเมื่อเปิดแอปเสร็จ ผู้คนอาจสัมผัสได้ถึงแสงแฟลชที่ไม่พึงประสงค์ระหว่างหน้าจอเปิดใช้กับหน้าจอแรกของแอป
“หน้าจอเปิดตัวไม่ใช่โอกาสในการสร้างแบรนด์ อย่าออกแบบประสบการณ์การเข้าใช้งานที่ดูเหมือนหน้าจอเริ่มต้นหรือหน้าต่าง "เกี่ยวกับ" อย่าใส่โลโก้หรือองค์ประกอบการสร้างแบรนด์อื่นๆ เว้นแต่ว่าเป็นส่วนคงที่ในหน้าจอแรกของแอปของคุณ”
การใช้หน้าจอเริ่มต้นเพื่อจุดประสงค์ในการโหลดหรือสร้างแบรนด์อาจทำให้เวลาใช้งานครั้งแรกช้าลงและทำให้ผู้ใช้รู้สึกว่าแอปทำงานช้า
เมื่อคุณเริ่มโปรเจ็กต์ iOS ใหม่ LaunchScreen.storyboard
เปล่าจะถูกสร้างขึ้น หน้าจอนี้จะแสดงให้ผู้ใช้เห็นในขณะที่แอปโหลดตัวควบคุมมุมมองและเลย์เอาต์
เพื่อให้แอปของคุณรู้สึกเร็วขึ้น คุณสามารถออกแบบหน้าจอเริ่มต้นให้คล้ายกับหน้าจอแรก (ตัวควบคุมการดู) ที่จะแสดงให้ผู้ใช้เห็น
ตัวอย่างเช่น หน้าจอเริ่มต้นของแอป Safari จะคล้ายกับมุมมองแรก :
สตอรี่บอร์ดของหน้าจอเปิดใช้นั้นเหมือนกับไฟล์สตอรีบอร์ดอื่นๆ ยกเว้นว่าคุณสามารถใช้คลาส UIKit มาตรฐานเท่านั้น เช่น UIViewController, UITabBarController และ UINavigationController หากคุณพยายามใช้คลาสย่อยที่กำหนดเองอื่นๆ (เช่น UserViewController) Xcode จะแจ้งให้คุณทราบว่าห้ามใช้ชื่อคลาสที่กำหนดเอง
สิ่งที่ควรทราบอีกประการหนึ่งคือ UIActivityIndicatorView
จะไม่เคลื่อนไหวเมื่อวางบนหน้าจอเริ่มต้น เนื่องจาก iOS จะสร้างภาพนิ่งจากกระดานเรื่องราวหน้าจอเปิดตัวและแสดงให้ผู้ใช้เห็น (มีการกล่าวถึงสั้น ๆ ในการนำเสนอ WWDC 2014 “ Platforms State of the Union” ประมาณ 01:21:56
น.)
นอกจากนี้ HIG ของ Apple ยังแนะนำว่าอย่าใส่ข้อความในหน้าจอการเริ่มใช้งาน เนื่องจากหน้าจอการเปิดใช้เป็นแบบคงที่ และคุณไม่สามารถแปลข้อความเพื่อรองรับภาษาต่างๆ ได้
การอ่านที่แนะนำ : แอพมือถือพร้อมคุณสมบัติจดจำใบหน้า: วิธีทำให้เป็นจริง
3. การฟื้นฟูสถานะสำหรับผู้ควบคุมการดู
การเก็บรักษาและการกู้คืนสถานะทำให้ผู้ใช้สามารถกลับสู่สถานะ UI เดิมได้ตั้งแต่ก่อนออกจากแอป บางครั้ง เนื่องจากหน่วยความจำไม่เพียงพอ ระบบปฏิบัติการอาจจำเป็นต้องลบแอพของคุณออกจากหน่วยความจำในขณะที่แอพอยู่ในพื้นหลัง และแอพอาจสูญเสียการติดตามสถานะ UI ล่าสุด หากไม่ได้รับการรักษาไว้ อาจทำให้ผู้ใช้สูญเสียงาน กำลังดำเนินการ!
ในหน้าจอมัลติทาสก์ เราจะเห็นรายการแอพที่วางไว้เบื้องหลัง เราอาจสันนิษฐานว่าแอปเหล่านี้ยังคงทำงานในพื้นหลัง ในความเป็นจริง แอพเหล่านี้บางตัวอาจถูกระบบฆ่าและรีสตาร์ทเนื่องจากความต้องการหน่วยความจำ สแนปชอตของแอปที่เราเห็นในมุมมองมัลติทาสก์เป็นภาพหน้าจอที่ระบบถ่ายโดยทันทีเมื่อเราออกจากแอป (เช่น ไปที่หน้าจอหลักหรือหน้าจอมัลติทาสก์)
iOS ใช้ภาพหน้าจอเหล่านี้เพื่อสร้างภาพลวงตาว่าแอปยังคงทำงานอยู่หรือยังคงแสดงมุมมองนี้อยู่ ในขณะที่แอปอาจถูกยกเลิกหรือรีสตาร์ทในพื้นหลังแล้วในขณะที่ยังแสดงภาพหน้าจอเดิม
คุณเคยมีประสบการณ์ในการเรียกใช้แอปจากหน้าจอมัลติทาสก์ว่าแอปแสดงอินเทอร์เฟซผู้ใช้ที่แตกต่างจากสแน็ปช็อตที่แสดงในมุมมองมัลติทาสก์หรือไม่ เนื่องจากแอปไม่ได้ใช้กลไกการกู้คืนสถานะ และข้อมูลที่แสดงหายไปเมื่อแอปถูกฆ่าในเบื้องหลัง การดำเนินการนี้อาจนำไปสู่ประสบการณ์ที่ไม่ดี เนื่องจากผู้ใช้คาดว่าแอปของคุณจะอยู่ในสถานะเดียวกับเมื่อออกจากแอป
จากบทความของ Apple:
“พวกเขาคาดหวังว่าแอปของคุณจะอยู่ในสถานะเดียวกับตอนที่ออกจากแอป การเก็บรักษาและการกู้คืนสถานะทำให้มั่นใจได้ว่าแอปของคุณจะกลับสู่สถานะก่อนหน้าเมื่อเปิดใช้งานอีกครั้ง”
UIKit ทำงานมากมายเพื่อลดความซับซ้อนในการรักษาและกู้คืนสถานะสำหรับเรา: จัดการการบันทึกและการโหลดสถานะของแอปโดยอัตโนมัติในเวลาที่เหมาะสม สิ่งที่เราต้องทำคือเพิ่มการกำหนดค่าบางอย่างเพื่อบอกให้แอปสนับสนุนการเก็บรักษาและการกู้คืนสถานะ และเพื่อบอกแอปว่าข้อมูลใดที่ต้องได้รับการเก็บรักษาไว้
ในการเปิดใช้งานการบันทึกและกู้คืนสถานะ เราสามารถใช้สองวิธีนี้ใน AppDelegate.swift
:
func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { return true }
func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { return true }
การดำเนินการนี้จะบอกให้แอปบันทึกและกู้คืนสถานะของแอปพลิเคชันโดยอัตโนมัติ
ต่อไป เราจะบอกแอปว่าต้องรักษามุมมองตัวควบคุมใดไว้ เราทำได้โดยระบุ "รหัสการกู้คืน" ในกระดานเรื่องราว :
คุณยังสามารถเลือก “ใช้ Storyboard ID” เพื่อใช้ ID กระดานเรื่องราวเป็น ID การกู้คืนได้อีกด้วย
ในการตั้งค่ารหัสการคืนค่าในโค้ด เราสามารถใช้คุณสมบัติ restorationIdentifier
ของตัวควบคุมการดู
// ViewController.swift self.restorationIdentifier = "MainVC"
ระหว่างการรักษาสถานะ ตัวควบคุมมุมมองหรือมุมมองใดๆ ที่ได้รับมอบหมายตัวระบุการกู้คืนจะมีสถานะบันทึกลงในดิสก์
ตัวระบุการฟื้นฟูสามารถจัดกลุ่มเข้าด้วยกันเพื่อสร้างเส้นทางการฟื้นฟู ตัวระบุถูกจัดกลุ่มโดยใช้ลำดับชั้นของมุมมอง จากตัวควบคุมรูทไปยังตัวควบคุมมุมมองแอ็คทีฟปัจจุบัน สมมติว่า MyViewController ฝังอยู่ในตัวควบคุมการนำทาง ซึ่งฝังอยู่ในตัวควบคุมแถบแท็บอื่น สมมติว่าพวกเขากำลังใช้ชื่อคลาสของตัวเองเป็นตัวระบุการคืนค่า เส้นทางการกู้คืนจะมีลักษณะดังนี้:
TabBarController/NavigationController/MyViewController
เมื่อผู้ใช้ออกจากแอปโดยให้ MyViewController เป็นตัวควบคุมมุมมองแอ็คทีฟ เส้นทางนี้จะถูกบันทึกโดยแอป จากนั้นแอปจะจำลำดับชั้นการดูก่อนหน้าที่แสดง ( ตัวควบคุมแถบแท็บ → ตัว ควบคุมการนำทาง → ตัวควบคุม มุมมองของฉัน )
หลังจากกำหนดตัวระบุการคืนค่าแล้ว เราจะต้องใช้เมธอด encodeRestorableState(พร้อม coder:) และ decodeRestorableState(พร้อม coder:) สำหรับแต่ละตัวควบคุมมุมมองที่สงวนไว้ สองวิธีนี้ช่วยให้เราระบุข้อมูลที่ต้องบันทึกหรือโหลด และวิธีการเข้ารหัสหรือถอดรหัส
มาดูตัวควบคุมการดู:
// MyViewController.swift // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { // will be called during state preservation override func encodeRestorableState(with coder: NSCoder) { // encode the data you want to save during state preservation coder.encode(self.username, forKey: "username") super.encodeRestorableState(with: coder) } // will be called during state restoration override func decodeRestorableState(with coder: NSCoder) { // decode the data saved and load it during state restoration if let restoredUsername = coder.decodeObject(forKey: "username") as? String { self.username = restoredUsername } super.decodeRestorableState(with: coder) } }
อย่าลืมเรียกใช้ superclass ที่ด้านล่างวิธีการของคุณเอง เพื่อให้แน่ใจว่าคลาสพาเรนต์มีโอกาสที่จะบันทึกและกู้คืนสถานะ
เมื่อวัตถุถอดรหัสเสร็จแล้ว applicationFinishedRestoringState()
จะถูกเรียกเพื่อบอกตัวควบคุมการดูว่าสถานะได้รับการคืนค่าแล้ว เราสามารถอัปเดต UI สำหรับตัวควบคุมการดูในวิธีนี้
// MyViewController.swift // MARK: State restoration // UIViewController already conforms to UIStateRestoring protocol by default extension MyViewController { ... override func applicationFinishedRestoringState() { // update the UI here self.usernameLabel.text = self.username } }
ที่นั่นคุณมีมัน! นี่เป็นวิธีการที่จำเป็นในการดำเนินการรักษาและกู้คืนสถานะสำหรับแอปของคุณ โปรดทราบว่าระบบปฏิบัติการจะลบสถานะที่บันทึกไว้เมื่อแอปถูกบังคับปิดโดยผู้ใช้ เพื่อหลีกเลี่ยงไม่ให้ติดค้างอยู่ในสถานะที่ใช้งานไม่ได้ในกรณีที่มีสิ่งผิดปกติเกิดขึ้นกับการรักษาและกู้คืนสถานะ
นอกจากนี้ อย่าจัดเก็บข้อมูลแบบจำลองใดๆ (เช่น ข้อมูลที่ควรจะบันทึกไว้ใน UserDefaults หรือ Core Data) ไว้ในสถานะ แม้ว่าอาจดูเหมือนสะดวกที่จะทำเช่นนั้นก็ตาม ข้อมูลสถานะจะถูกลบออกเมื่อผู้ใช้บังคับออกจากแอปของคุณ และคุณจะไม่ต้องการสูญเสียข้อมูลโมเดลด้วยวิธีนี้อย่างแน่นอน
ในการทดสอบว่าการรักษาและฟื้นฟูสภาพทำงานได้ดีหรือไม่ ให้ทำตามขั้นตอนด้านล่าง:
- สร้างและเปิดใช้แอปโดยใช้ Xcode
- ไปที่หน้าจอด้วยการเก็บรักษาและการกู้คืนสถานะที่คุณต้องการทดสอบ
- กลับไปที่หน้าจอหลัก (โดยการปัดขึ้นหรือดับเบิลคลิกปุ่มโฮม หรือกด Shift ⇧ + Cmd ⌘ + H ในโปรแกรมจำลอง) เพื่อส่งแอปไปที่พื้นหลัง
- หยุดแอปใน Xcode โดยกดปุ่ม
- เปิดแอปอีกครั้งและตรวจสอบว่าสถานะได้รับการกู้คืนสำเร็จหรือไม่
เนื่องจากส่วนนี้ครอบคลุมเฉพาะพื้นฐานของการรักษาและฟื้นฟูสภาพเท่านั้น ฉันจึงแนะนำบทความต่อไปนี้โดย Apple Inc. สำหรับความรู้เชิงลึกเพิ่มเติมเกี่ยวกับการฟื้นฟูสถานะ:
- การรักษาและฟื้นฟูสภาพ
- กระบวนการถนอม UI
- กระบวนการฟื้นฟู UI
4. ลดการใช้มุมมองที่ไม่ทึบแสงให้มากที่สุด
มุมมองทึบแสงเป็นมุมมองที่ไม่มีความโปร่งใส หมายความว่าองค์ประกอบ UI ใดๆ ที่วางอยู่ด้านหลังจะไม่ปรากฏให้เห็นเลย เราสามารถตั้งค่าให้มุมมองทึบแสงในตัวสร้างอินเทอร์เฟซ:
หรือเราสามารถทำได้โดยทางโปรแกรมด้วยคุณสมบัติ isOpaque
ของ UIView:
view.isOpaque = true
การตั้งค่ามุมมองเป็นแบบทึบจะทำให้ระบบการวาดปรับประสิทธิภาพการวาดบางส่วนในขณะที่แสดงผลหน้าจอ
หากมุมมองมีความโปร่งใส (เช่น อัลฟ่าต่ำกว่า 1.0) iOS จะต้องทำงานพิเศษเพื่อคำนวณสิ่งที่ควรแสดงโดยการผสมเลเยอร์ต่างๆ ของมุมมองในลำดับชั้นของมุมมอง ในทางกลับกัน หากมุมมองถูกตั้งค่าเป็นทึบ ระบบการวาดจะวางมุมมองนี้ไว้ข้างหน้า และหลีกเลี่ยงการทำงานพิเศษของการผสมเลเยอร์มุมมองหลายชั้นที่อยู่ด้านหลัง
คุณสามารถตรวจสอบว่าเลเยอร์ใดกำลังผสม (ไม่ทึบแสง) ใน iOS Simulator ได้โดยตรวจสอบ Debug → Color Blended Layers
หลังจากตรวจสอบตัวเลือก Color Blended Layers แล้ว คุณจะเห็นว่าบางมุมมองเป็นสีแดงและบางส่วนเป็นสีเขียว สีแดงแสดงว่ามุมมองไม่ทึบแสง และการแสดงผลเป็นผลลัพธ์จากเลเยอร์ที่ซ้อนอยู่ด้านหลัง สีเขียวแสดงว่าภาพไม่ชัดและไม่มีการผสม
ป้ายกำกับที่แสดงด้านบน (“ดูเพื่อน” เป็นต้น) จะถูกเน้นด้วยสีแดง เนื่องจากเมื่อลากป้ายกำกับไปที่กระดานเรื่องราว สีพื้นหลังของป้ายกำกับจะถูกตั้งค่าให้โปร่งใสโดยค่าเริ่มต้น เมื่อระบบการวาดกำลังจัดองค์ประกอบการแสดงผลใกล้กับพื้นที่ฉลาก ระบบจะถามถึงเลเยอร์ด้านหลังฉลากและทำการคำนวณ
วิธีหนึ่งที่คุณสามารถเพิ่มประสิทธิภาพแอปได้คือการลดจำนวนการดูที่ถูกเน้นด้วยสีแดงให้มากที่สุด
ด้วยการเปลี่ยน label.backgroundColor = UIColor.clear
เป็น label.backgroundColor = UIColor.white
เราสามารถลดการผสมเลเยอร์ระหว่างป้ายกำกับและเลเยอร์การดูด้านหลังได้
คุณอาจสังเกตเห็นว่า แม้ว่าคุณจะตั้งค่า UIImageView เป็นแบบทึบแสงและกำหนดสีพื้นหลังให้กับมัน ตัวจำลองจะยังคงแสดงสีแดงในมุมมองภาพ อาจเป็นเพราะภาพที่คุณใช้สำหรับการดูภาพมีช่องอัลฟา
หากต้องการลบช่องอัลฟาของรูปภาพ คุณสามารถใช้แอปดูตัวอย่างเพื่อสร้างภาพซ้ำ ( Shift ⇧ + Cmd ⌘ + S ) และยกเลิกการเลือกช่องทำเครื่องหมาย "Alpha" เมื่อบันทึก
5. ส่งฟังก์ชันการประมวลผลจำนวนมากไปยังเธรดพื้นหลัง (GCD)
เนื่องจาก UIKit ใช้งานได้กับเธรดหลักเท่านั้น การประมวลผลจำนวนมากบนเธรดหลักจะทำให้ UI ช้าลง UIKit ใช้เธรดหลักไม่เพียงเพื่อจัดการและตอบสนองต่ออินพุตของผู้ใช้เท่านั้น แต่ยังเพื่อวาดหน้าจอ
กุญแจสำคัญในการทำให้แอปตอบสนองคือการย้ายงานการประมวลผลจำนวนมากไปยังเธรดพื้นหลังให้ได้มากที่สุด หลีกเลี่ยงการทำการคำนวณที่ซับซ้อน การสร้างเครือข่าย และการดำเนินการ IO จำนวนมาก (เช่น การอ่านและการเขียนลงดิสก์) บนเธรดหลัก
คุณอาจเคยใช้แอปที่ไม่ตอบสนองต่อการป้อนข้อมูลแบบสัมผัสในทันใด และรู้สึกเหมือนกับว่าแอปหยุดทำงาน สาเหตุส่วนใหญ่อาจเกิดจากแอปที่ใช้งานการคำนวณจำนวนมากบนเธรดหลัก
เธรดหลักมักจะสลับไปมาระหว่างงาน UIKit (เช่น การจัดการอินพุตของผู้ใช้) และงานเบาบางงานในช่วงเวลาเล็กน้อย หากงานหนักกำลังทำงานบนเธรดหลัก UIKit จะต้องรอจนกว่างานหนักจะเสร็จสิ้นก่อนที่จะสามารถจัดการอินพุตแบบสัมผัสได้
โดยค่าเริ่มต้น โค้ดภายในวิธีวงจรชีวิตของตัวควบคุมมุมมอง (เช่น viewDidLoad) และฟังก์ชัน IBOutlet จะถูกดำเนินการบนเธรดหลัก ในการย้ายงานการประมวลผลจำนวนมากไปยังเธรดพื้นหลัง เราสามารถใช้คิว Grand Central Dispatch ที่ Apple จัดหาให้
นี่คือเทมเพลตสำหรับการสลับคิว:
// Switch to background thread to perform heavy task. DispatchQueue.global(qos: .default).async { // Perform heavy task here. // Switch back to main thread to perform UI-related task. DispatchQueue.main.async { // Update UI. } }
qos
หมายถึง "คุณภาพของการบริการ" ค่าคุณภาพการบริการที่แตกต่างกันบ่งบอกถึงลำดับความสำคัญที่แตกต่างกันสำหรับงานที่ระบุ ระบบปฏิบัติการจะจัดสรรเวลา CPU และปริมาณการประมวลผล I/O ของพลังงาน CPU สำหรับงานที่จัดสรรในคิวที่มีค่า QoS สูงกว่า ซึ่งหมายความว่างานจะเสร็จเร็วขึ้นในคิวที่มีค่า QoS สูงกว่า ค่า QoS ที่สูงขึ้นจะใช้พลังงานมากขึ้นเนื่องจากใช้ทรัพยากรมากขึ้น
นี่คือรายการค่า QoS จากลำดับความสำคัญสูงสุดไปต่ำสุด:
Apple ได้จัดเตรียมตารางที่มีประโยชน์พร้อมตัวอย่างค่า QoS ที่จะใช้สำหรับงานต่างๆ
สิ่งหนึ่งที่ต้องจำไว้คือควรรันโค้ด UIKit ทั้งหมดบนเธรดหลักเสมอ การแก้ไขอ็อบเจ็กต์ UIKit (เช่น UILabel
และ UIImageView
) บนเธรดพื้นหลังอาจมีผลที่ไม่ได้ตั้งใจ เช่น UI ที่ไม่ได้อัปเดตจริงๆ เกิดการขัดข้อง และอื่นๆ
จากบทความของ Apple:
“การอัปเดต UI บนเธรดอื่นที่ไม่ใช่เธรดหลักเป็นข้อผิดพลาดทั่วไปที่อาจส่งผลให้พลาดการอัปเดต UI, ข้อบกพร่องด้านภาพ, ข้อมูลเสียหาย และการขัดข้อง”
ฉันแนะนำให้ดูวิดีโอ WWDC 2012 ของ Apple เกี่ยวกับการทำงานพร้อมกันของ UI เพื่อให้เข้าใจวิธีสร้างแอปที่ตอบสนองได้ดียิ่งขึ้น
หมายเหตุ
ข้อเสียของการเพิ่มประสิทธิภาพคือคุณต้องเขียนโค้ดเพิ่มเติมหรือกำหนดการตั้งค่าเพิ่มเติมนอกเหนือจากฟังก์ชันการทำงานของแอป การทำเช่นนี้อาจทำให้แอปของคุณส่งช้ากว่าที่คาดไว้ และคุณจะมีโค้ดเพิ่มเติมที่จะรักษาในอนาคต และโค้ดที่มากขึ้นหมายถึงข้อบกพร่องที่มากขึ้น
ก่อนที่จะใช้เวลาในการเพิ่มประสิทธิภาพแอปของคุณ ให้ถามตัวเองว่าแอปนั้นราบรื่นอยู่แล้วหรือไม่ หรือมีส่วนที่ไม่ตอบสนองซึ่งจำเป็นต้องได้รับการปรับให้เหมาะสมจริงๆ หรือไม่ การใช้เวลามากในการปรับแต่งแอปที่ราบรื่นอยู่แล้วเพื่อกำจัด 0.01 วินาทีอาจไม่คุ้มค่า เนื่องจากอาจต้องใช้เวลาในการพัฒนาคุณลักษณะหรือลำดับความสำคัญอื่นๆ ที่ดีขึ้น
แหล่งข้อมูลเพิ่มเติม
- “A Suite of Delicious iOS Eye Candy,” Tim Oliver, งาน Tokyo iOS Meetup 2018 (วิดีโอ)
- “การสร้างอินเทอร์เฟซผู้ใช้พร้อมกันบน iOS” Andy Matuschak, WWDC 2012 (วิดีโอ)
- “การรักษา UI ของแอพของคุณตลอดการเปิดตัว” Apple
- “คู่มือการเขียนโปรแกรมการทำงานพร้อมกัน: คิวการส่ง” เอกสารจัดเก็บเอกสาร Apple
- “ตัวตรวจสอบเธรดหลัก” Apple