การสร้างระบบการออกแบบเพื่อรองรับผลิตภัณฑ์เดียวไม่ใช่เรื่องง่าย - ต้องแข็งแกร่งและยืดหยุ่นไปพร้อม ๆ กันเพื่อให้สามารถปรับขนาดได้ แม้ว่าจะมีความท้าทาย แต่ทรัพยากรที่ยอดเยี่ยมมากมายได้แบ่งปันหลักการและแนวทางที่เป็นประโยชน์ที่ช่วยให้ทีมสร้างระบบที่ดีทั้งทางภาพและทางโปรแกรม บทความนี้พยายามที่จะสนับสนุนพื้นที่ที่ไม่มีใครแตะต้องโดยเน้นที่การสร้างระบบที่ดีใน SwiftUI
ยืนบนไหล่ของพวกเขา .
ทำไมฉันถึงเขียนบทความนี้
ในช่วงฤดูร้อนแรกของฉันที่ ITP ที่นิวยอร์ก ฉันโชคดีที่มีโอกาสได้ทำงานเป็นนักพัฒนา iOS ฝึกงานที่ Line Break Studio งานหนึ่งที่ฉันได้รับมอบหมายให้ทำคือสร้างระบบการออกแบบในสองขั้นตอน:ขั้นแรกให้เห็นภาพใน Sketch และโดยทางโปรแกรมใน SwiftUI
. ประสบการณ์ในการทดลองกับเฟรมเวิร์กใหม่และสร้างระบบการออกแบบนั้นน่าทึ่งมาก แต่ก็ยังมีปัญหาระหว่างทาง นั่นเป็นเหตุผลที่เราต้องการแบ่งปันประสบการณ์ของเรากับชุมชน โดยหวังว่าจะทำให้กระบวนการพัฒนาของคุณง่ายขึ้น
SwiftUI คืออะไร
Apple เปิดตัวเฟรมเวิร์กใหม่ที่ก้าวล้ำนี้ใน WWDC 2019 ซึ่งเป็นหนึ่งในเฟรมเวิร์กที่ดีที่สุดในรอบหลายปี จากมุมมองของนักพัฒนาเว็บ ประสบการณ์การพัฒนาโครงการใน SwiftUI
ใกล้เคียงกับสแต็กและเฟรมเวิร์กส่วนหน้าแบบเดิม
นี่เป็นการเคลื่อนไหวที่ยอดเยี่ยมอย่างแน่นอนเพราะอินเทอร์เฟซการเขียนโปรแกรมและสถานะการจัดการนั้นง่ายกว่าเมื่อก่อนอย่างมาก และส่วนที่ดีที่สุดของการปรับปรุงนี้คือสามารถรวม UIKit และ SwiftUI ได้อย่างราบรื่น หากต้องการเรียนรู้พื้นฐานของ SwiftUI บทแนะนำอย่างเป็นทางการของ Apple มีประโยชน์มาก
โครงการสาธิต
เพื่อจุดประสงค์ในการสาธิต ฉันสร้างเวอร์ชันที่เรียบง่ายของระบบการออกแบบที่เราสร้างขึ้นใน Line Break Studio เป็นชุดของปุ่ม ส่วนประกอบในรูปแบบต่างๆ ซึ่งสร้างขึ้นจากส่วนบนของส่วนล่างสองส่วน:ตัวพิมพ์ และ จานสี .
โครงการนี้เป็นสาธารณะบน GitHub และฉันใช้ Xcode 11 Beta 5
เพื่อการพัฒนา ฐาน Airtable ที่เป็นศูนย์กลางการจัดการระบบการออกแบบ (อ่านเพิ่มเติมเกี่ยวกับการจัดการเวิร์กโฟลว์) เป็นแบบสาธารณะสำหรับการอ้างอิง
หลักการของระบบออกแบบอาคาร
ระบบการออกแบบในโค้ดคือมิดเดิลแวร์ระหว่างนักออกแบบและนักพัฒนา ผู้พัฒนาระบบรับอินพุตจากระบบการออกแบบในรูปแบบภาพ และสร้าง API ที่เหมือนกันสำหรับการพัฒนาต่อไป ควรปฏิบัติตามหลักการสองข้อต่อไปนี้เพื่อให้ระบบนี้สมบูรณ์ในรหัส:
1. สื่อสารกับโทเค็น
โดยพื้นฐานแล้ว จุดประสงค์ของการมีระบบการออกแบบในโปรแกรมไม่ได้เกี่ยวกับการจัดการโค้ดหรือประสิทธิภาพการพัฒนาที่ดีขึ้น แต่เพื่อให้แน่ใจว่ามุมมอง สอดคล้องกับไฟล์การออกแบบ เพื่อให้บรรลุเป้าหมายนั้น การใช้โทเค็นเพื่อแสดงสี แบบอักษร ขนาด หรือองค์ประกอบภาพใดๆ เป็นสิ่งสำคัญในการรักษาคุณภาพของการสื่อสารระหว่างนักพัฒนา นักออกแบบ และผู้จัดการในทีม
2. ระดับของลำดับชั้น
ในบทความของ EightShapes ชี้ให้เห็นว่าเราควร "แสดงตัวเลือกก่อน แล้วค่อยตัดสินใจต่อไป" เพราะ "คุณไม่สามารถตัดสินใจได้หากไม่มีตัวเลือก"
สถาปัตยกรรมการจัดลำดับประเภทนี้จะคลายระดับของการเชื่อมต่อระหว่างระดับต่างๆ ดังนั้นจึงให้ความยืดหยุ่นและไดนามิกมากขึ้นสำหรับการแก้ไขที่เป็นไปได้ วิธีที่ฉันจัดโครงสร้างระดับอยู่ในลำดับจากล่างขึ้นบน:วัสดุ → ฐาน → โทเค็น แต่อย่างไรก็ตามทีมก็สบายใจได้อยู่แล้ว
ดำน้ำในโค้ด
ส่วนต่อไปนี้เป็นรายการไฮไลท์ที่เราต้องการชี้ให้เห็นตามประสบการณ์ของเรา โปรดไปที่ repo GitHub สำหรับรหัสที่สมบูรณ์ คำติชมหรือนักวิจารณ์สามารถปรับปรุงได้
1. ระดับการจัดลำดับชั้นทางสถาปัตยกรรม
มีสองวิธีในการซ้อนวัสดุที่ระดับล่างเพื่อสร้างโทเค็นที่ระดับสูงสุด:
- ใช้
enum
เพื่อความปลอดภัยในการพิมพ์และการรู้รหัส
ข้อดีของการใช้ enum ในโค้ดเป็นตัวแบ่งกลุ่มหรือพารามิเตอร์ในฟังก์ชันเป็นที่ทราบกันดีอยู่แล้ว ประเด็นหนึ่งที่ควรกล่าวถึงในที่นี้คือการนำระดับของลำดับชั้นไปใช้
เราเก็บค่าดิบไว้เสมอ รวมทั้งขนาดตัวอักษร (CGFloat
) และชื่อฟอนต์ (String
) ที่ระดับต่ำสุดเพราะเราไม่ต้องการยุ่งกับมัน แต่เนื่องจากค่า raw ต้องเป็นตัวอักษรใน enum เราจึงไม่สามารถกำหนด case
ได้ ให้เป็นค่าจากอีนุมอื่น
เพื่อแก้ไขปัญหานี้ เราใช้ฟังก์ชัน getValue
ซึ่งคืนค่าดิบใน switch
กรณีจำเป็น
- ใช้
struct
เพื่อโครงสร้างที่ง่ายขึ้น
แม้ว่า enum จะยอดเยี่ยม แต่เราไม่ต้องการคุณลักษณะเฉพาะในบางกรณี ตัวอย่างเช่น เนื่องจาก Xcode
ดูแลงานหนักในการประมวลผลสีแบบไดนามิก และไม่จำเป็นต้องใช้ตัวเลือกพารามิเตอร์ในจุดปลาย API เราสามารถตั้งค่าจานสีโดยใช้โครงสร้างสองระดับอย่างง่าย
2. การตั้งชื่อ API
. ที่ชัดเจนและตรงไปตรงมา จุดสิ้นสุด
แบบแผนการตั้งชื่อเป็นหัวข้อกว้างๆ อีกหัวข้อหนึ่งสำหรับการอภิปรายและอภิปราย นอกเหนือจากอนุสัญญาพื้นฐานของ Swift แล้ว กฎสองข้อที่เราปฏิบัติตามคือ 1) ไม่มีตัวย่อ และ 2) ทำให้ง่าย ตัวอย่างเช่น ในการใช้ระบบการพิมพ์และสี แทนที่จะสร้างปลายทางใหม่ เราสร้างส่วนขยายจากโครงสร้างแบบอักษรและสี วิธีนี้ช่วยลดความพยายามในการจดจำชื่อ API ที่ไม่คุ้นเคยสำหรับนักพัฒนา
3. จัดการชุดสีแบบไดนามิกในสองโหมด
ดังนั้นโหมดมืดจึงกลายเป็นมาตรฐานในอุตสาหกรรม และทั้งทีม iOS และ Android ได้ใช้คุณสมบัตินี้ เป็นเทรนด์ที่ดีสำหรับผู้ใช้ แต่อาจสร้างความท้าทายให้กับนักออกแบบและนักพัฒนา รวมถึงการจัดการและการตั้งชื่อชุดสี โดยเฉพาะอย่างยิ่งชุดระดับสีเทา
ในการคิดและสื่อสารเกี่ยวกับระดับสีเทาแบบไดนามิก โดยใช้คำเช่น สีขาว , ไฟ , ดำ หรือ มืด ไม่ทำงาน เพราะถ้าเราอ้างถึงไดนามิกสี #000000
(สีดำใน HEX) สีดำ หรือมืด ใน light color scheme
คุณจะพูดถึงสีนี้ได้อย่างไรซึ่งควรเปลี่ยนเป็น #FFFFFF
(สีขาวใน HEX) ใน dark color scheme
? defaultDark หรือ lightDark ?
ทำให้เกิดความสับสนอย่างมากในการตั้งชื่อชุดสีไดนามิกระดับสีเทาในแนวทางทั่วไป เพื่อหลีกเลี่ยงความสับสนนี้ เราใช้ theme
และ contrast
เพื่อจัดการชุดสีหนึ่งชุดใน light
และ dark
แบบแผนแทน
โปรดทราบว่าไม่จำเป็นต้องสลับสีระดับสีเทาในโหมดสีตรงข้ามเสมอไป ในสถานการณ์ที่สีอ่อนยังคงสว่างและสีเข้มยังคงเป็นสีเข้ม เราเพียงแค่ตั้งชื่อว่าสีอ่อนหรือสีเข้มแทน
เมื่อเราสรุปวิธีการตั้งชื่อนี้แล้ว การจัดการสถาปัตยกรรมของจานสีนี้ทำได้ง่ายใน Xcode
. ในการสร้างชุดสี เพียงแค่สร้าง Asset Catalog
. ใหม่ file → เพิ่ม Color Set
. ใหม่ → และเปลี่ยน Appearances
ถึง Any, Light, Dark
จะทำ
4. environment
การตั้งค่า
คุณลักษณะที่ยอดเยี่ยมอย่างหนึ่งในเฟรมเวิร์ก SwiftUI คือตัวแก้ไขสภาพแวดล้อม ซึ่งให้ความสามารถในการควบคุมค่าสภาพแวดล้อมในมุมมองเป้าหมาย ในแง่ของระบบการออกแบบอาคาร ความสามารถนี้ช่วยอำนวยความสะดวกในการเปลี่ยนแบบอักษรของแอปที่ระดับราก และข้อดีอีกอย่างของการใช้ environmentValue
คือการเปลี่ยนแปลงและทดสอบโทนสีอ่อนและสีเข้มในการพัฒนา
5. buttonStyle
และป้ายปุ่ม
เมื่อเทียบกับสมัยก่อนใน UIKit การสร้างปุ่มที่ใช้ซ้ำได้ใน SwiftUI นั้นง่ายกว่าอย่างมาก มุมมองปุ่มประกอบด้วยสองส่วนคือ action
ปิด (เหตุการณ์ที่จะเริ่มทำงานเมื่อกดปุ่ม) และ label
(เนื้อความของปุ่ม). มุมมองนั้นสามารถเชื่อมโยงกับตัวดัดแปลง buttonStyle
. หากต้องการเรียนรู้รายละเอียดเกี่ยวกับการสร้างปุ่มที่ใช้ซ้ำได้ ฉันแนะนำให้อ่านบทแนะนำของ Alejandro ซึ่งครอบคลุมและมีประโยชน์
ในส่วนประกอบปุ่มที่กำหนดเองของเรา ขั้นตอนแรกคือการสร้างสองโครงสร้าง รวมถึง TokenButtonLabel
และ TokenButtonStyle
. โครงสร้างทั้งสองนี้ได้รับการตั้งโปรแกรมตามประเภทของปุ่มที่เรามีในไฟล์การออกแบบ ตัวอย่างเช่น ป้ายกำกับมีเพียงสองประเภทเท่านั้น ได้แก่ ไอคอนและข้อความ แต่ละประเภทมี init
. ตาม ฟังก์ชันที่ออกแบบด้วยพารามิเตอร์ต่างๆ สำหรับอินสแตนซ์ใหม่
ในทางกลับกัน มีรูปแบบปุ่มสี่ประเภทหลัก:ไอคอนวงกลม ไอคอน แคปซูล และข้อความ เพื่อติดตาม ButtonStyle
โปรโตคอล makeBody
ต้องดำเนินการ func ฟังก์ชันนี้ทำให้เรามี configuration
คุณสมบัติโดยให้ isPressed
. ดั้งเดิม ค่าที่จะตรวจสอบว่ามีการกดปุ่มหรือไม่
สุดท้ายวางทับ TokenButtonLabel
และ TokenButtonStyle
จุดสิ้นสุดของ API คอมโพเนนต์ปุ่มจะเป็น TokenButton
- การจัดกลุ่มที่รวมเนื้อหาและรูปแบบของปุ่มเข้าด้วยกัน สอดคล้องกับประเภทปุ่มในระบบการออกแบบภาพ
6. AnyView
เป็นเครื่องห่อ
ในขณะที่เรากำลังจัดการกับ makeBody
ฟังก์ชันนำโดย ButtonStyle
โปรโตคอล เราพบเคล็ดลับที่เป็นประโยชน์ในการทำงานกับ View
. ในการจัดเก็บมุมมองในตัวแปร ประเภทคำอธิบายประกอบสามารถระบุเป็น AnyView
ซึ่งทำงานเป็นคอนเทนเนอร์มุมมองทั่วไปใน SwiftUI
ในกรณีของเรา เนื่องจากเราต้องการเพิ่มตัวแก้ไขความทึบให้กับ configuration.label
ไปยังปุ่มทุกประเภท แทนที่จะทำซ้ำในแต่ละ switch
กรณีควรโยงตัวดัดแปลงในตอนท้ายโดยสิ้นเชิง เราสามารถบรรลุรูปแบบนี้ได้โดยใช้ข้อดีของ AnyView
ด้วยวิธีนี้:
7. สร้างตัวแก้ไขมุมมองด้วย mutating
ฟังก์ชัน
ในการอัปเดตรูปแบบของปุ่มแบบไดนามิก เราสามารถสร้างตัวปรับแต่งของเราเองได้ ขั้นแรกให้ยกตัวอย่างคุณสมบัติสถานะที่ไม่แน่นอนที่กำหนดเองในมุมมอง จากนั้นสร้าง mutating
ฟังก์ชันที่ส่งคืน Self
พิมพ์หลังจากอัปเดตคุณสมบัติสถานะเป้าหมาย
8. รูปแบบเส้นขอบที่หากิน
ข้อเสียประการหนึ่งของ SwiftUI คือ การใส่สไตล์ให้เป็นรูปวงกลมที่มีขอบเป็นวงกลมนั้นไม่ตรงไปตรงมาเลย ฉันพยายามอยู่พักหนึ่ง และในที่สุดก็พบวิธีแก้ปัญหาที่นี่ใน StackOverflow A clipShape
และ overlay
จำเป็นต้องมีตัวปรับแต่งเพื่อให้มันทำงาน
บทสรุป
SwiftUI เป็นการปรับปรุงที่เหลือเชื่อที่ Apple ทำ แม้ว่าข้อบกพร่องยังคงมีอยู่ แต่การสร้างระบบการออกแบบที่แข็งแกร่งและยืดหยุ่นด้วยมัน และ UI ที่ซับซ้อนยิ่งขึ้นใน iOS ก็มีประสิทธิภาพมากกว่าที่เคย ฉันหวังว่าบทความนี้จะเป็นประโยชน์สำหรับทีม iOS ที่พยายามสร้าง UI และยินดีต้อนรับทุกคำติชม!
? อ่านผลงานของฉันเพิ่มเติมได้ที่ vinceshao.com / ติดตามฉันทาง Twitter หรือ LinkedIn