Composable Architecture (เรียกสั้นๆ ว่า TCA) คือไลบรารีสำหรับการสร้างแอปพลิเคชันในลักษณะที่สอดคล้องกันและเข้าใจง่าย โดยคำนึงถึงองค์ประกอบ การทดสอบ และการยศาสตร์ สามารถใช้ใน SwiftUI, UIKit และอื่นๆ และบนแพลตฟอร์ม Apple ใดๆ (iOS, macOS, visionOS, tvOS และ watchOS)
สถาปัตยกรรมแบบคอมโพสิตคืออะไร?
เรียนรู้เพิ่มเติม
ตัวอย่าง
การใช้งานขั้นพื้นฐาน
เอกสารประกอบ
ชุมชน
การติดตั้ง
การแปล
ไลบรารีนี้มีเครื่องมือหลักบางประการที่สามารถใช้ในการสร้างแอปพลิเคชันที่มีวัตถุประสงค์และความซับซ้อนที่แตกต่างกัน โดยนำเสนอเรื่องราวที่น่าสนใจที่คุณสามารถติดตามได้เพื่อแก้ไขปัญหาต่างๆ มากมายที่คุณพบในแต่ละวันเมื่อสร้างแอปพลิเคชัน เช่น:
การจัดการของรัฐ
วิธีจัดการสถานะของแอปพลิเคชันของคุณโดยใช้ประเภทค่าอย่างง่าย และแชร์สถานะผ่านหลายหน้าจอ เพื่อให้สามารถสังเกตการเปลี่ยนแปลงในหน้าจอหนึ่งได้ทันทีในอีกหน้าจอหนึ่ง
องค์ประกอบ
วิธีแบ่งคุณลักษณะขนาดใหญ่ออกเป็นส่วนประกอบเล็กๆ ซึ่งสามารถแยกออกเป็นโมดูลที่แยกออกจากกันของตัวมันเอง และติดกาวกลับเข้าด้วยกันเพื่อสร้างคุณลักษณะได้อย่างง่ายดาย
ผลข้างเคียง
จะทำให้บางส่วนของแอปพลิเคชันสื่อสารกับโลกภายนอกด้วยวิธีที่สามารถทดสอบและเข้าใจได้มากที่สุดเท่าที่จะเป็นไปได้
การทดสอบ
วิธีที่ไม่เพียงแต่จะทดสอบคุณสมบัติที่สร้างขึ้นในสถาปัตยกรรมเท่านั้น แต่ยังเขียนการทดสอบการรวมสำหรับคุณสมบัติที่ประกอบด้วยหลายส่วน และเขียนการทดสอบแบบ end-to-end เพื่อทำความเข้าใจว่าผลข้างเคียงส่งผลต่อแอปพลิเคชันของคุณอย่างไร สิ่งนี้ช่วยให้คุณรับประกันได้ว่าตรรกะทางธุรกิจของคุณกำลังทำงานในแบบที่คุณคาดหวัง
การยศาสตร์
วิธีดำเนินการทั้งหมดข้างต้นให้สำเร็จใน API แบบง่ายๆ โดยมีแนวคิดและส่วนที่เคลื่อนไหวน้อยที่สุด
Composable Architecture ได้รับการออกแบบในหลายตอนของ Point-Free ซึ่งเป็นซีรีส์วิดีโอที่สำรวจการเขียนโปรแกรมเชิงฟังก์ชันและภาษา Swift ซึ่งดำเนินรายการโดย Brandon Williams และ Stephen Celis
คุณสามารถรับชมตอนทั้งหมดได้ที่นี่ รวมถึงทัวร์ชมสถาปัตยกรรมหลายส่วนโดยเฉพาะตั้งแต่เริ่มต้น
การซื้อคืนนี้มาพร้อมกับตัวอย่าง มากมาย เพื่อสาธิตวิธีการแก้ไขปัญหาทั่วไปและปัญหาที่ซับซ้อนด้วยสถาปัตยกรรมแบบผสมได้ ลองเข้าไปดูไดเรกทอรีนี้เพื่อดูทั้งหมด รวมถึง:
กรณีศึกษา
เริ่มต้นใช้งาน
ผลกระทบ
การนำทาง
ตัวลดลำดับที่สูงขึ้น
ส่วนประกอบที่ใช้ซ้ำได้
ผู้จัดการสถานที่
ผู้จัดการการเคลื่อนไหว
ค้นหา
การรู้จำเสียง
แอป SyncUps
โอเอกซ์
สิ่งที่ต้องทำ
บันทึกเสียง
กำลังมองหาบางสิ่งที่สำคัญกว่านี้อยู่ใช่ไหม? ตรวจสอบซอร์สโค้ดสำหรับ isowords เกมค้นหาคำบน iOS ที่สร้างใน SwiftUI และสถาปัตยกรรมแบบเขียนได้
บันทึก
หากต้องการดูบทช่วยสอนแบบโต้ตอบทีละขั้นตอน โปรดดูที่ Meet the Composable Architecture
หากต้องการสร้างคุณลักษณะโดยใช้สถาปัตยกรรมแบบคอมโพสิต คุณต้องกำหนดประเภทและค่าบางประเภทที่เป็นแบบจำลองโดเมนของคุณ:
สถานะ : ประเภทที่อธิบายข้อมูลที่ฟีเจอร์ของคุณจำเป็นต้องใช้ในการดำเนินการตามตรรกะและแสดงผล UI
การดำเนินการ : ประเภทที่แสดงถึงการกระทำทั้งหมดที่สามารถเกิดขึ้นได้ในฟีเจอร์ของคุณ เช่น การกระทำของผู้ใช้ การแจ้งเตือน แหล่งที่มาของเหตุการณ์ และอื่นๆ
ตัวลด : ฟังก์ชันที่อธิบายวิธีพัฒนาสถานะปัจจุบันของแอปเป็นสถานะถัดไปเมื่อมีการดำเนินการ ตัวลดยังรับผิดชอบในการส่งคืนเอฟเฟกต์ใด ๆ ที่ควรรัน เช่น คำขอ API ซึ่งสามารถทำได้โดยการส่งคืนค่า Effect
ร้านค้า : รันไทม์ที่ขับเคลื่อนฟีเจอร์ของคุณอย่างแท้จริง คุณส่งการกระทำของผู้ใช้ทั้งหมดไปยังร้านค้าเพื่อให้ร้านค้าสามารถเรียกใช้ตัวลดและเอฟเฟกต์ได้ และคุณสามารถสังเกตการเปลี่ยนแปลงสถานะในร้านค้าเพื่อให้คุณสามารถอัปเดต UI ได้
ประโยชน์ของการทำเช่นนี้คือ คุณจะปลดล็อกความสามารถในการทดสอบฟีเจอร์ของคุณได้ทันที และคุณจะสามารถแยกฟีเจอร์ขนาดใหญ่ที่ซับซ้อนออกเป็นโดเมนเล็กๆ ที่สามารถรวมเข้าด้วยกันได้
เป็นตัวอย่างพื้นฐาน ให้พิจารณา UI ที่แสดงตัวเลขพร้อมกับปุ่ม "+" และ "−" ที่เพิ่มขึ้นและลดตัวเลข เพื่อให้สิ่งที่น่าสนใจ สมมติว่ามีปุ่มที่เมื่อแตะแล้วจะสร้างคำขอ API เพื่อดึงข้อเท็จจริงแบบสุ่มเกี่ยวกับตัวเลขนั้นและแสดงในมุมมอง
ในการใช้คุณสมบัตินี้ เราจะสร้างประเภทใหม่ที่จะเก็บโดเมนและลักษณะการทำงานของคุณสมบัตินั้น และจะมีคำอธิบายประกอบด้วยมาโคร @Reducer
:
นำเข้าคุณสมบัติ ComposableArchitecture@Reducerstruct {}
ในที่นี้ เราจำเป็นต้องกำหนดประเภทของสถานะของคุณลักษณะ ซึ่งประกอบด้วยจำนวนเต็มสำหรับการนับปัจจุบัน เช่นเดียวกับสตริงทางเลือกที่แสดงถึงข้อเท็จจริงที่กำลังนำเสนอ:
@Reducerstruct Feature { @ObservableState struct State: Equatable { var count = 0 var numberFact: String? -
บันทึก
เราได้ใช้แมโคร @ObservableState
กับ State
เพื่อใช้ประโยชน์จากเครื่องมือสังเกตการณ์ในไลบรารี
เรายังจำเป็นต้องกำหนดประเภทของการกระทำของคุณลักษณะด้วย มีการกระทำที่ชัดเจน เช่น การแตะปุ่มลด ปุ่มเพิ่ม หรือปุ่มข้อเท็จจริง แต่ก็มีบางส่วนที่ไม่ชัดเจนเช่นกัน เช่น การกระทำที่เกิดขึ้นเมื่อเราได้รับการตอบกลับจากคำขอ API ข้อเท็จจริง:
@Reducerstruct คุณลักษณะ { @ObservableState struct State: Equatable { /* ... */ } enum Action { case decreationButtonTapped case increatButtonTapped case numberFactButtonTapped case numberFactResponse(String) }}
จากนั้นเราจะใช้คุณสมบัติ body
ซึ่งมีหน้าที่ในการเขียนตรรกะและพฤติกรรมที่แท้จริงสำหรับคุณลักษณะนั้น ในนั้น เราสามารถใช้ตัว Reduce
เพื่ออธิบายวิธีเปลี่ยนสถานะปัจจุบันไปเป็นสถานะถัดไป และเอฟเฟกต์ใดบ้างที่จำเป็นต้องดำเนินการ การดำเนินการบางอย่างไม่จำเป็นต้องดำเนินการกับเอฟเฟกต์ และสามารถส่งคืน .none
เพื่อแสดงสิ่งนั้น:
@Reducerstruct Feature { @ObservableState struct State: Equatable { /* ... */ } enum Action { /* ... */ } var body: some ลด{ ลด { state, action in สลับการกระทำ { case .decreationButtonTapped: state.count -= 1 กลับ .none case .increationButtonTapped: state.count += 1 return .none case .numberFactButtonTapped: return .run { [count = state.count] ส่งเข้าให้ (data, _) = ลองรอ URLSession.shared.data( จาก: URL (สตริง: "http://numbersapi.com/(count)/trivia")! ) รอการส่ง ( .numberFactResponse(String(decoding: data, as: UTF8.self)) ) } case ให้ .numberFactResponse(fact): state.numberFact = ความเป็นจริงกลับ .none } } }}
และสุดท้ายเราก็กำหนดมุมมองที่แสดงคุณลักษณะนี้ โดยจะเก็บ StoreOf
เพื่อให้สามารถสังเกตการเปลี่ยนแปลงทั้งหมดในสถานะและแสดงผลอีกครั้ง และเราสามารถส่งการกระทำของผู้ใช้ทั้งหมดไปยังร้านค้าเพื่อให้สถานะเปลี่ยนแปลง:
struct FeatureView: ดู { ให้เก็บ: StoreOfvar body: บางมุมมอง { แบบฟอร์ม { ส่วน { ข้อความ (" (store.count)") ปุ่ม ("การลดลง") { store.send (.decreatButtonTapped) } ปุ่ม ( "ส่วนเพิ่ม") { store.send(.increationButtonTapped) } } ส่วน { ปุ่ม("ข้อเท็จจริงเกี่ยวกับตัวเลข") { store.send(.numberFactButtonTapped) } } ถ้าให้ข้อเท็จจริง = store.numberFact { ข้อความ (ข้อเท็จจริง) } } }}
นอกจากนี้ยังตรงไปตรงมาที่จะให้ตัวควบคุม UIKit ออกจากร้านนี้ คุณสามารถสังเกตการเปลี่ยนแปลงสถานะในร้านค้าได้ใน viewDidLoad
จากนั้นเติมส่วนประกอบ UI ด้วยข้อมูลจากร้านค้า โค้ดยาวกว่าเวอร์ชัน SwiftUI เล็กน้อย ดังนั้นเราจึงสรุปไว้ที่นี่:
คลาส FeatureViewController: UIViewController { ให้เก็บ: StoreOfinit (ร้านค้า: StoreOf ) { self.store = store super.init(nibName: nil, Bundle: nil) } จำเป็นต้องมี init?(coder: NSCoder) { fatalError("init(coder:) has not been allowance") } แทนที่ func viewDidLoad() { super.viewDidLoad() ให้ countLabel = UILabel() ให้ decreatButton = UIButton() ให้ increatButton = UIButton() ให้ factLabel = UILabel() // ละไว้: เพิ่มการดูย่อยและตั้งค่าข้อจำกัด... สังเกต { [ตนเองอ่อนแอ] เข้าไป ระวังปล่อยให้ตัวเอง อื่น ๆ { กลับ } countLabel.text = "(self.store.text)" factLabel.text = self.store.numberFact } } @objc func increatButtonTapped() { self.store.send(.increatButtonTapped) } @objc ส่วนตัว func decreatButtonTapped() { self.store.send(.decreatButtonTapped) } @objc ส่วนตัว func factButtonTapped () { self.store.send (.numberFactButtonTapped) }}
เมื่อเราพร้อมที่จะแสดงมุมมองนี้ เช่น ในจุดเริ่มต้นของแอป เราก็สามารถสร้างร้านค้าได้ ซึ่งสามารถทำได้โดยการระบุสถานะเริ่มต้นเพื่อเริ่มแอปพลิเคชัน เช่นเดียวกับตัวลดที่จะจ่ายพลังงานให้กับแอปพลิเคชัน:
นำเข้า ComposableArchitecture@mainstruct MyApp: แอป { var body: บางฉาก { WindowGroup { FeatureView( ร้านค้า: ร้านค้า (initialState: Feature.State ()) { คุณลักษณะ () } ) } }}
และนั่นก็เพียงพอแล้วที่จะได้บางสิ่งบนหน้าจอเพื่อเล่นด้วย แน่นอนว่าต้องใช้ขั้นตอนมากกว่าที่คุณทำด้วยวิธีวานิลลา SwiftUI เล็กน้อย แต่มีประโยชน์บางประการ มันทำให้เรามีวิธีที่สอดคล้องกันในการใช้การกลายพันธุ์ของสถานะ แทนที่จะกระจายลอจิกในออบเจ็กต์ที่สังเกตได้บางส่วน และในการปิดการดำเนินการต่างๆ ของส่วนประกอบ UI นอกจากนี้ยังช่วยให้เราแสดงผลข้างเคียงได้อย่างกระชับอีกด้วย และเราสามารถทดสอบตรรกะนี้ได้ทันที รวมถึงผลกระทบต่างๆ โดยไม่ต้องทำงานเพิ่มเติมมากนัก
บันทึก
สำหรับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับการทดสอบ โปรดดูบทความการทดสอบโดยเฉพาะ
หากต้องการทดสอบให้ใช้ TestStore
ซึ่งสามารถสร้างได้ด้วยข้อมูลเดียวกับ Store
แต่จะมีการทำงานเพิ่มเติมเพื่อให้คุณสามารถยืนยันได้ว่าคุณลักษณะของคุณพัฒนาไปอย่างไรเมื่อมีการส่งการกระทำ:
@Testfunc พื้นฐาน() async { ให้ store = TestStore(initialState: Feature.State()) { คุณลักษณะ() }}
เมื่อสร้างร้านค้าทดสอบแล้ว เราสามารถใช้มันเพื่อยืนยันขั้นตอนของผู้ใช้ทั้งหมดได้ แต่ละขั้นตอนเราต้องพิสูจน์ว่าสถานะเปลี่ยนวิธีที่เราคาดหวัง ตัวอย่างเช่น เราสามารถจำลองกระแสผู้ใช้ในการแตะที่ปุ่มเพิ่มและลด:
// ทดสอบว่าการแตะที่ปุ่มเพิ่ม/ลดจะเป็นการเปลี่ยนแปลง countawait store.send(.increatButtonTapped) { $0.count = 1}รอ store.send(.decreatButtonTapped) { $0.จำนวน = 0}
นอกจากนี้ หากขั้นตอนหนึ่งทำให้เกิดผลกระทบที่จะดำเนินการ ซึ่งจะดึงข้อมูลกลับเข้าไปในที่จัดเก็บ เราต้องยืนยันในสิ่งนั้น ตัวอย่างเช่น หากเราจำลองผู้ใช้ที่แตะปุ่มข้อเท็จจริง เราคาดหวังว่าจะได้รับการตอบกลับข้อเท็จจริงพร้อมกับข้อเท็จจริง ซึ่งจะทำให้สถานะ numberFact
ถูกเติม:
รอ store.send (.numberFactButtonTapped) รอ store.receive (.numberFactResponse) { $0.numberFact = ???}
อย่างไรก็ตาม เราจะรู้ได้อย่างไรว่าข้อเท็จจริงใดบ้างที่จะถูกส่งกลับมาให้เรา?
ขณะนี้ตัวลดของเรากำลังใช้เอฟเฟกต์ที่เข้าถึงโลกแห่งความเป็นจริงเพื่อโจมตีเซิร์ฟเวอร์ API และนั่นหมายความว่าเราไม่สามารถควบคุมพฤติกรรมของมันได้ เรากำลังเผชิญกับการเชื่อมต่ออินเทอร์เน็ตและความพร้อมใช้งานของเซิร์ฟเวอร์ API เพื่อเขียนการทดสอบนี้
จะดีกว่าถ้าการพึ่งพานี้ถูกส่งผ่านไปยังตัวลดเพื่อให้เราสามารถใช้การพึ่งพาแบบสดเมื่อเรียกใช้แอปพลิเคชันบนอุปกรณ์ แต่ใช้การขึ้นต่อกันที่จำลองสำหรับการทดสอบ เราสามารถทำได้โดยการเพิ่มคุณสมบัติให้กับตัวลด Feature
:
@Reducerstruct Feature { ให้ numberFact: (Int) async พ่น -> String -
จากนั้นเราสามารถใช้มันในการดำเนินการ reduce
:
กรณี .numberFactButtonTapped: return .run { [count = state.count] ส่งเข้ามา ให้ข้อเท็จจริง = ลองรอ self.numberFact(นับ) รอส่ง(.numberFactResponse(fact)) }
และในจุดเริ่มต้นของแอปพลิเคชัน เราสามารถจัดเตรียมเวอร์ชันของการขึ้นต่อกันที่โต้ตอบกับเซิร์ฟเวอร์ API ในโลกแห่งความเป็นจริงได้จริง:
@mainstruct MyApp: แอป { var body: บางฉาก { WindowGroup { FeatureView( ร้านค้า: ร้านค้า (initialState: Feature.State ()) { คุณสมบัติ ( numberFact: { หมายเลขเข้าให้ (ข้อมูล _) = ลองรอ URLSession.shared.data( จาก: URL (สตริง: "http://numbersapi.com/(number)")! ) ส่งคืนสตริง (ถอดรหัส: ข้อมูลเป็น: UTF8.self) } ) } ) } }}
แต่ในการทดสอบ เราสามารถใช้การพึ่งพาจำลองที่ส่งคืนข้อเท็จจริงที่กำหนดและคาดเดาได้ในทันที:
@Testfunc basics() async { la store = TestStore(initialState: Feature.State()) { Feature(numberFact: { "($0) is a good number Brent" }) }}
ด้วยการทำงานล่วงหน้าเพียงเล็กน้อย เราสามารถเสร็จสิ้นการทดสอบได้โดยการจำลองผู้ใช้แตะที่ปุ่มข้อเท็จจริง จากนั้นรับการตอบสนองจากการขึ้นต่อกันเพื่อนำเสนอข้อเท็จจริง:
รอ store.send (.numberFactButtonTapped) รอ store.receive (.numberFactResponse) { $0.numberFact = "0 เป็นตัวเลขที่ดีของเบรนต์"}
นอกจากนี้เรายังสามารถปรับปรุงหลักสรีรศาสตร์ของการใช้การพึ่งพา numberFact
ในแอปพลิเคชันของเราได้อีกด้วย เมื่อเวลาผ่านไป แอปพลิเคชันอาจมีการพัฒนาเป็นฟีเจอร์มากมาย และฟีเจอร์บางอย่างอาจต้องการเข้าถึง numberFact
และการส่งต่ออย่างชัดเจนผ่านทุกเลเยอร์อาจสร้างความรำคาญได้ มีกระบวนการที่คุณสามารถปฏิบัติตามเพื่อ "ลงทะเบียน" การขึ้นต่อกันกับไลบรารี ทำให้พร้อมใช้งานได้ทันทีกับทุกเลเยอร์ในแอปพลิเคชัน
บันทึก
สำหรับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับการจัดการการขึ้นต่อกัน โปรดดูบทความการขึ้นต่อกันโดยเฉพาะ
เราสามารถเริ่มต้นด้วยการรวมฟังก์ชันข้อเท็จจริงเชิงตัวเลขในรูปแบบใหม่:
struct NumberFactClient { การดึงข้อมูล: (Int) async พ่น -> สตริง}
จากนั้นลงทะเบียนประเภทนั้นกับระบบการจัดการการขึ้นต่อกันโดยทำให้ไคลเอนต์สอดคล้องกับโปรโตคอล DependencyKey
ซึ่งกำหนดให้คุณต้องระบุค่าปัจจุบันที่จะใช้เมื่อรันแอปพลิเคชันในเครื่องจำลองหรืออุปกรณ์:
ส่วนขยาย NumberFactClient: DependencyKey { คงที่ ให้ liveValue = ตนเอง ( ดึงข้อมูล: { number in la (data, _) = try await URLSession.shared .data(from: URL(string: "http://numbersapi.com/(number)")! ) return String(decoding: data, เป็น: UTF8.self) } )}ส่วนขยาย DependencyValues { var numberFact: NumberFactClient { รับ { self[NumberFactClient.self] } ตั้ง { ตนเอง [NumberFactClient.self] = ค่าใหม่ } }}
ด้วยการทำงานล่วงหน้าเล็กน้อย คุณสามารถเริ่มใช้การพึ่งพาในฟีเจอร์ใด ๆ ได้ทันทีโดยใช้ wrapper คุณสมบัติ @Dependency
:
@รีดิวเซอร์ struct คุณลักษณะ {- ให้ numberFact: (Int) async พ่น -> String+ @Dependency(.numberFact) var numberFact …- ลองรอ self.numberFact(count)+ ลองรอ self.numberFact.fetch(count) -
โค้ดนี้ทำงานได้เหมือนเมื่อก่อน แต่คุณไม่จำเป็นต้องผ่านการพึ่งพาอย่างชัดเจนอีกต่อไปเมื่อสร้างตัวลดของคุณลักษณะ เมื่อเรียกใช้แอปในการแสดงตัวอย่าง เครื่องจำลอง หรือบนอุปกรณ์ จะมีการจัดหาการขึ้นต่อกันแบบสดให้กับตัวลด และในการทดสอบ จะมีการจัดเตรียมการขึ้นต่อกันของการทดสอบ
ซึ่งหมายความว่าจุดเริ่มต้นไปยังแอปพลิเคชันไม่จำเป็นต้องสร้างการขึ้นต่อกันอีกต่อไป:
@mainstruct MyApp: แอป { var body: บางฉาก { WindowGroup { FeatureView( ร้านค้า: ร้านค้า (initialState: Feature.State ()) { คุณลักษณะ () } ) } }}
และสามารถสร้างร้านค้าทดสอบได้โดยไม่ต้องระบุการขึ้นต่อกันใดๆ แต่คุณยังสามารถแทนที่การขึ้นต่อกันใดๆ ที่คุณต้องการเพื่อวัตถุประสงค์ของการทดสอบได้:
ให้ store = TestStore (initialState: Feature.State()) { Feature()} withDependencies: { $0.numberFact.fetch = { "($0) เป็นตัวเลขที่ดีของเบรนต์" }}// ...
นั่นคือพื้นฐานของการสร้างและทดสอบฟีเจอร์ในสถาปัตยกรรมที่เขียนได้ ยังมี อีกหลาย สิ่งที่ต้องสำรวจ เช่น การจัดองค์ประกอบ โมดูลาร์ ความสามารถในการปรับตัว และเอฟเฟกต์ที่ซับซ้อน ไดเร็กทอรีตัวอย่างมีโปรเจ็กต์มากมายให้สำรวจเพื่อดูการใช้งานขั้นสูงเพิ่มเติม
เอกสารสำหรับการเผยแพร่และ main
มีอยู่ที่นี่:
main
1.17.0 (คู่มือการโยกย้าย)
1.16.0 (คู่มือการโยกย้าย)
1.15.0 (คู่มือการโยกย้าย)
1.14.0 (คู่มือการโยกย้าย)
1.13.0 (คู่มือการย้ายข้อมูล)
1.12.0 (คู่มือการย้ายข้อมูล)
1.11.0 (คู่มือการย้ายข้อมูล)
1.10.0 (คู่มือการย้ายข้อมูล)
1.9.0 (คู่มือการโยกย้าย)
1.8.0 (คู่มือการโยกย้าย)
1.7.0 (คู่มือการย้ายข้อมูล)
1.6.0 (คู่มือการโยกย้าย)
1.5.0 (คู่มือการโยกย้าย)
1.4.0 (คู่มือการโยกย้าย)
1.3.0
1.2.0
1.1.0
1.0.0
0.59.0
0.58.0
0.57.0
มีบทความจำนวนหนึ่งในเอกสารประกอบที่คุณอาจพบว่ามีประโยชน์เมื่อคุณคุ้นเคยกับห้องสมุดมากขึ้น:
เริ่มต้นใช้งาน
การพึ่งพาอาศัยกัน
การทดสอบ
การนำทาง
สถานะการแบ่งปัน
ผลงาน
เห็นพ้องต้องกัน
การผูก
หากคุณต้องการหารือเกี่ยวกับสถาปัตยกรรมแบบเขียนได้หรือมีคำถามเกี่ยวกับวิธีการใช้งานเพื่อแก้ไขปัญหาเฉพาะ มีสถานที่หลายแห่งที่คุณสามารถพูดคุยกับผู้ที่หลงใหลใน Point-Free ได้:
สำหรับการสนทนาในรูปแบบยาว เราขอแนะนำแท็บการสนทนาของที่เก็บนี้
สำหรับการสนทนาแบบไม่เป็นทางการ เราขอแนะนำ Point-Free Community slack
คุณสามารถเพิ่ม ComposableArchitecture ให้กับโปรเจ็กต์ Xcode ได้โดยการเพิ่มเป็นการขึ้นต่อกันของแพ็คเกจ
จากเมนู ไฟล์ เลือก เพิ่มการพึ่งพาแพ็คเกจ...
ป้อน "https://github.com/pointfreeco/swift-composable-architecture" ลงในช่องข้อความ URL ที่เก็บแพ็กเกจ
ขึ้นอยู่กับโครงสร้างโครงการของคุณ:
หากคุณมีแอปพลิเคชันเป้าหมายเดียวที่ต้องการเข้าถึงไลบรารี ให้เพิ่ม ComposableArchitecture ลงในแอปพลิเคชันของคุณโดยตรง
หากคุณต้องการใช้ไลบรารีนี้จากเป้าหมาย Xcode หลายรายการ หรือผสมเป้าหมาย Xcode และเป้าหมาย SPM คุณต้องสร้างเฟรมเวิร์กที่ใช้ร่วมกันซึ่งขึ้นอยู่กับ ComposableArchitecture จากนั้นขึ้นอยู่กับเฟรมเวิร์กนั้นในเป้าหมายทั้งหมดของคุณ สำหรับตัวอย่างนี้ ลองดูแอปพลิเคชันสาธิต Tic-Tac-Toe ซึ่งแบ่งคุณสมบัติจำนวนมากออกเป็นโมดูล และใช้ไลบรารีแบบคงที่ในลักษณะนี้โดยใช้แพ็คเกจ Tic-Tac-Toe Swift
Composable Architecture สร้างขึ้นโดยคำนึงถึงความสามารถในการขยาย และมีไลบรารีที่สนับสนุนโดยชุมชนจำนวนหนึ่งที่พร้อมใช้งานเพื่อปรับปรุงแอปพลิเคชันของคุณ:
คุณสมบัติพิเศษของสถาปัตยกรรมแบบผสมได้: ไลบรารีที่ใช้ร่วมกับสถาปัตยกรรมแบบผสมได้
TCAComposer: เฟรมเวิร์กแมโครสำหรับสร้างโค้ด boiler-plate ในสถาปัตยกรรมที่ประกอบได้
TCACoordinators: รูปแบบผู้ประสานงานในสถาปัตยกรรมแบบผสมได้
หากคุณต้องการสนับสนุนห้องสมุด โปรดเปิดประชาสัมพันธ์พร้อมลิงก์ไปยังห้องสมุดนั้น!
การแปล README นี้ได้รับการสนับสนุนโดยสมาชิกของชุมชน:
ภาษาอาหรับ
ภาษาฝรั่งเศส
ฮินดี
ชาวอินโดนีเซีย
ภาษาอิตาลี
ญี่ปุ่น
เกาหลี
ขัด
โปรตุเกส
ภาษารัสเซีย
จีนตัวย่อ
สเปน
ภาษายูเครน
หากคุณต้องการสนับสนุนการแปล โปรดเปิดประชาสัมพันธ์พร้อมลิงก์ไปยัง Gist!
เรามีบทความเฉพาะสำหรับคำถามและความคิดเห็นที่พบบ่อยที่สุดที่ผู้คนมีเกี่ยวกับห้องสมุด
บุคคลต่อไปนี้ให้ข้อเสนอแนะเกี่ยวกับห้องสมุดตั้งแต่เริ่มแรกและช่วยทำให้ห้องสมุดเป็นเช่นทุกวันนี้:
พอล โคลตัน, คาน เดเดโอกลู, แมตต์ ดิเอปเฮาส์, โจเซฟ โดเลชาล, เอมานทาส, แมทธิว จอห์นสัน, จอร์จ ไคมาคัส, นิกิต้า เลโอนอฟ, คริสโตเฟอร์ ลิสซิโอ, เจฟฟรีย์ แม็คโก, อเลฮานโดร มาร์ติเนซ, ไช มิชาลี, วิลลิส พลัมเมอร์, ไซมอน-ปิแอร์ รอย, จัสติน ไพรซ์, สเวน เอ. ชมิดต์ ไคล์ เชอร์แมน, ปีเตอร์ ชิม่า, ยาสเดฟ ซิงห์, แม็กซิม สเมียร์นอฟ, ไรอัน สโตน, แดเนียล Hollis Tavares และสมาชิก Point-Free ทุกคน ?.
ขอขอบคุณเป็นพิเศษสำหรับ Chris Liscio ที่ช่วยเราฝ่าฟันนิสัยแปลกๆ ของ SwiftUI มากมาย และช่วยปรับแต่ง API สุดท้าย
และต้องขอบคุณ Shai Mishali และโปรเจ็กต์ CombineCommunity ซึ่งเราได้นำ Publishers.Create
ไปใช้ ซึ่งเราใช้ใน Effect
เพื่อช่วยเชื่อมโยง API ของผู้รับมอบสิทธิ์และการโทรกลับ ทำให้อินเทอร์เฟซกับเฟรมเวิร์กของบุคคลที่สามง่ายขึ้นมาก
Composable Architecture ถูกสร้างขึ้นบนรากฐานของแนวคิดที่เริ่มต้นโดยห้องสมุดอื่นๆ โดยเฉพาะ Elm และ Redux
นอกจากนี้ยังมีไลบรารีสถาปัตยกรรมมากมายในชุมชน Swift และ iOS แต่ละสิ่งเหล่านี้มีชุดลำดับความสำคัญและข้อเสียของตัวเองที่แตกต่างจากสถาปัตยกรรมแบบประกอบได้
ซี่โครง
วนซ้ำ
รีสวิฟท์
ขั้นตอนการทำงาน
เครื่องปฏิกรณ์Kit
RxFeedback
โมเบียส สวิฟท์
ฟลักเซอร์
PromisedArchitectureKit
ไลบรารีนี้เผยแพร่ภายใต้ใบอนุญาต MIT ดูใบอนุญาตสำหรับรายละเอียด