Skip to content

Instantly share code, notes, and snippets.

@akashsoni01
Last active June 3, 2023 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akashsoni01/b358ee0b3b747167964ef6946123c88d to your computer and use it in GitHub Desktop.
Save akashsoni01/b358ee0b3b747167964ef6946123c88d to your computer and use it in GitHub Desktop.

The Composable Architecture

CI Slack

कम्पोज़ेबल आर्किटेक्चर (TCA, शॉर्ट के लिए) एक संगत में अनुप्रयोगों के निर्माण के लिए एक लाइब्रेरी है और समझने योग्य तरीका, रचना, परीक्षण और एर्गोनॉमिक्स को ध्यान में रखते हुए। इसमें इस्तेमाल किया जा सकता है SwiftUI, UIKit, और बहुत कुछ, और किसी भी Apple प्लेटफ़ॉर्म (iOS, macOS, tvOS, और watchOS) पर।

कंपोज़ेबल आर्किटेक्चर क्या है?

यह लाइब्रेरी कुछ मुख्य उपकरण प्रदान करता है जो वास्तव में अलग-अलग उद्देश्यों का उपयोग करता है और फ्रैंचाइजी के निर्माण के लिए किया जा सकता है गुण, यह सम्मोहक कहानियां प्रदान करती हैं, जिससे आप अपने सामने आने वालों को कई तरह से हल कर सकते हैं कमांड का निर्माण करते समय दिन-प्रतिदिन, जैसे:

  • स्टेट मैनेजमेंट
    सरल मूल्य प्रकारों का उपयोग करके अपने आवेदन की स्थिति का प्रबंधन कैसे करें, और राज्य भर में साझा करें कई स्क्रीन ताकि एक स्क्रीन में म्यूटेशन तुरंत दूसरे स्क्रीन में देखा जा सके|

  • कम्पोजीशन
    बड़ी फीचर्स को छोटे घटकों में कैसे विभाजित किया जाए, जिन्हें उनके स्वयं के अलग-अलग मॉड्यूल में निकाला जा सकता है और फीचर बनाने के लिए आसानी से एक साथ वापस मिलाया जा सकता है।

  • साइड इफेक्ट्स
    एप्लिकेशन के कुछ हिस्सों को बाहरी दुनिया से सबसे अधिक टेस्टाबले और समझने योग्य तरीके से कैसे कम्यूनिकेट करने दें।

  • टेस्टिंग
    न केवल आर्किटेक्चर में निर्मित फीचर का परीक्षण कैसे करें, बल्कि कई हिस्सों से बनी फीचर्स के लिए इंटीग्रेशन टेस्ट भी लिखें, और यह समझने के लिए एंड-टू-एंड टेस्ट लिखें कि साइड इफेक्ट आपके एप्लिकेशन को कैसे प्रभावित करते हैं। यह आपको मजबूत गारंटी देने की अनुमति देता है कि आपका व्यावसायिक तर्क आपकी अपेक्षा के अनुसार चल रहा है।

  • अर्गोनोमिक्स
    उपरोक्त सभी को सरल एपीआई में कुछ अवधारणाओं और यथासंभव चलती भागों के साथ कैसे पूरा करें।

और अधिक जानें

कंपोज़ेबल आर्किटेक्चर को Brandon Williams और Stephen Celis द्वारा होस्ट किए गए कार्यात्मक प्रोग्रामिंग और स्विफ्ट भाषा की खोज करने वाली एक वीडियो श्रृंखला प्वाइंट-फ्री पर कई एपिसोड के दौरान डिज़ाइन किया गया था।

आप यहां tca-episode-collection सभी एपिसोड देख सकते हैं, साथ ही स्क्रैच से आर्किटेक्चर का एक समर्पित, मल्टीपार्ट टूर tca-tour भी देख सकते हैं।

video poster image

उदाहरण

Screen shots of example applications यह रेपो बहुत सारे उदाहरणों के साथ आता है जो यह प्रदर्शित करता है कि कंपोज़ेबल आर्किटेक्चर के साथ सामान्य और जटिल समस्याओं को कैसे हल किया जाए। उन सभी को देखने के लिए इस निर्देशिका को देखें, जिनमें शामिल हैं:

कुछ और महत्वपूर्ण खोज रहे हैं? [isowords] gh-isowords के लिए स्रोत कोड देखें, a स्विफ्टयूआई और कंपोज़ेबल आर्किटेक्चर में निर्मित आईओएस वर्ड सर्च गेम।

मूल उपयोग

टिप्पणी चरण-दर-चरण इंटरएक्टिव ट्यूटोरियल के लिए, चेक आउट करना सुनिश्चित करें Meet the Composable Architecture.

कंपोज़ेबल आर्किटेक्चर का उपयोग करके एक फीचर बनाने के लिए आप उस मॉडल के कुछ प्रकारों और मूल्यों को परिभाषित करते हैं आपका डोमेन:

  • स्टेट: एक प्रकार जो उस डेटा का वर्णन करता है जिसे आपकी सुविधा को अपने तर्क को निष्पादित करने और उसे प्रस्तुत करने की आवश्यकता होती है यूआई।
  • एक्शन: एक प्रकार जो उन सभी क्रियाओं का प्रतिनिधित्व करता है जो आपकी सुविधा में हो सकती हैं, जैसे उपयोगकर्ता क्रियाएं, सूचनाएं, घटना स्रोत और बहुत कुछ।
  • रदूसर: एक फ़ंक्शन जो वर्णन करता है कि ऐप की वर्तमान स्थिति को अगली स्थिति में कैसे विकसित किया जाए राज्य ने एक कार्रवाई दी। रेड्यूसर किसी भी प्रभाव को वापस करने के लिए भी जिम्मेदार है जो कि होना चाहिए रन, जैसे एपीआई अनुरोध, जो एक प्रभाव मान लौटाकर किया जा सकता है।
  • स्टोर: वह रनटाइम जो वास्तव में आपकी सुविधा को संचालित करता है। आप स्टोर पर सभी उपयोगकर्ता क्रियाएं भेजते हैं ताकि स्टोर रेड्यूसर और प्रभाव चला सके, और आप स्टोर में स्थिति परिवर्तन देख सकें ताकि आप UI को अपडेट कर सकें।

ऐसा करने का लाभ यह है कि आप तुरंत अपनी सुविधा की परीक्षण क्षमता को अनलॉक कर देंगे, और आप बड़ी, जटिल विशेषताओं को छोटे डोमेन में विभाजित करने में सक्षम होंगे जिन्हें एक साथ चिपकाया जा सकता है।

एक बुनियादी उदाहरण के रूप में, एक यूआई पर विचार करें जो "+" और "-" बटनों के साथ एक संख्या दिखाता है जो वृद्धि करता है और संख्या घटाओ। चीजों को दिलचस्प बनाने के लिए, मान लीजिए कि एक बटन भी है कि कब टैप किया गया उस संख्या के बारे में एक यादृच्छिक तथ्य प्राप्त करने के लिए एक एपीआई अनुरोध करता है और फिर तथ्य को प्रदर्शित करता है एक चेतावनी।

इस सुविधा को लागू करने के लिए हम एक नया प्रकार बनाते हैं जिसमें डोमेन और व्यवहार शामिल होंगे विशेषता के अनुरूप ReducerProtocol:

import ComposableArchitecture

struct Feature: ReducerProtocol {
}

यहां हमें फीचर की स्थिति के लिए एक प्रकार को परिभाषित करने की आवश्यकता है, जिसमें एक पूर्णांक होता है वर्तमान गणना, साथ ही एक वैकल्पिक स्ट्रिंग जो उस अलर्ट के शीर्षक का प्रतिनिधित्व करती है जिसे हम दिखाना चाहते हैं (वैकल्पिक क्योंकि शून्य अलर्ट न दिखाने का प्रतिनिधित्व करता है):

struct Feature: ReducerProtocol {
  struct State: Equatable {
    var count = 0
    var numberFactAlert: String?
  }
}

हमें फीचर के कार्यों के लिए एक प्रकार को भी परिभाषित करने की आवश्यकता है। स्पष्ट क्रियाएं हैं, जैसे घटते बटन, वेतन वृद्धि बटन, या तथ्य बटन को टैप करना। लेकिन कुछ थोड़े से भी हैं गैर-स्पष्ट वाले, जैसे कि उपयोगकर्ता द्वारा अलर्ट को खारिज करने की क्रिया, और होने वाली क्रिया जब हम तथ्य एपीआई अनुरोध से प्रतिक्रिया प्राप्त करते हैं:

struct Feature: ReducerProtocol {
  struct State: Equatable {  }
  enum Action: Equatable {
    case factAlertDismissed
    case decrementButtonTapped
    case incrementButtonTapped
    case numberFactButtonTapped
    case numberFactResponse(TaskResult<String>)
  }
}

और फिर हम reduce पद्धति को लागू करते हैं जो वास्तविक तर्क को संभालने के लिए जिम्मेदार है और सुविधा के लिए व्यवहार यह वर्णन करता है कि वर्तमान स्थिति को अगले राज्य में कैसे बदला जाए, और वर्णन करता है कि किन प्रभावों को क्रियान्वित करने की आवश्यकता है। कुछ क्रियाओं को प्रभावों को निष्पादित करने की आवश्यकता नहीं होती है, और वे इसका प्रतिनिधित्व करने के लिए .none वापस कर सकते हैं:

struct Feature: ReducerProtocol {
  struct State: Equatable {  }
  enum Action: Equatable {}
  
  func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
    switch action {
      case .factAlertDismissed:
        state.numberFactAlert = nil
        return .none

      case .decrementButtonTapped:
        state.count -= 1
        return .none

      case .incrementButtonTapped:
        state.count += 1
        return .none

      case .numberFactButtonTapped:
        return .run { [count = state.count] send in
          await send(
            .numberFactResponse(
              TaskResult {
                String(
                  decoding: try await URLSession.shared
                    .data(from: URL(string: "http://numbersapi.com/\(count)/trivia")!).0,
                  as: UTF8.self
                )
              }
            )
          )
        }

      case let .numberFactResponse(.success(fact)):
        state.numberFactAlert = fact
        return .none

      case .numberFactResponse(.failure):
        state.numberFactAlert = "Could not load a number fact :("
        return .none
    }
  }
}

और फिर अंत में हम उस दृश्य को परिभाषित करते हैं जो सुविधा प्रदर्शित करता है। यह StoreOf<Feature> पर टिका रहता है ताकि यह राज्य में सभी परिवर्तनों का निरीक्षण कर सके और पुनः प्रस्तुत कर सके, और हम सभी उपयोगकर्ता क्रियाएं भेज सकें दुकान ताकि राज्य बदल जाए। हमें फैक्ट अलर्ट के आसपास एक स्ट्रक्चर रैपर भी पेश करना चाहिए इसे पहचान योग्य बनाएं, जिसे .अलर्ट दृश्य संशोधक के लिए आवश्यक है:

struct FeatureView: View {
  let store: StoreOf<Feature>

  var body: some View {
    WithViewStore(self.store, observe: { $0 }) { viewStore in
      VStack {
        HStack {
          Button("") { viewStore.send(.decrementButtonTapped) }
          Text("\(viewStore.count)")
          Button("+") { viewStore.send(.incrementButtonTapped) }
        }

        Button("Number fact") { viewStore.send(.numberFactButtonTapped) }
      }
      .alert(
        item: viewStore.binding(
          get: { $0.numberFactAlert.map(FactAlert.init(title:)) },
          send: .factAlertDismissed
        ),
        content: { Alert(title: Text($0.title)) }
      )
    }
  }
}

struct FactAlert: Identifiable {
  var title: String
  var id: String { self.title }
}

इस स्टोर से UIKit कंट्रोलर को संचालित करना भी सीधा है। आप सदस्यता लें UI को अपडेट करने और अलर्ट दिखाने के लिए viewDidLoad में स्टोर करें। कोड की तुलना में थोड़ा लंबा है SwiftUI संस्करण, इसलिए हमने इसे यहाँ संक्षिप्त कर दिया है:

Click to expand!
class FeatureViewController: UIViewController {
  let viewStore: ViewStoreOf<Feature>
  var cancellables: Set<AnyCancellable> = []

  init(store: StoreOf<Feature>) {
    self.viewStore = ViewStore(store)
    super.init(nibName: nil, bundle: nil)
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    let countLabel = UILabel()
    let incrementButton = UIButton()
    let decrementButton = UIButton()
    let factButton = UIButton()

    // Omitted: Add subviews and set up constraints...

    self.viewStore.publisher
      .map { "\($0.count)" }
      .assign(to: \.text, on: countLabel)
      .store(in: &self.cancellables)

    self.viewStore.publisher.numberFactAlert
      .sink { [weak self] numberFactAlert in
        let alertController = UIAlertController(
          title: numberFactAlert, message: nil, preferredStyle: .alert
        )
        alertController.addAction(
          UIAlertAction(
            title: "Ok",
            style: .default,
            handler: { _ in self?.viewStore.send(.factAlertDismissed) }
          )
        )
        self?.present(alertController, animated: true, completion: nil)
      }
      .store(in: &self.cancellables)
  }

  @objc private func incrementButtonTapped() {
    self.viewStore.send(.incrementButtonTapped)
  }
  @objc private func decrementButtonTapped() {
    self.viewStore.send(.decrementButtonTapped)
  }
  @objc private func factButtonTapped() {
    self.viewStore.send(.numberFactButtonTapped)
  }
}

एक बार जब हम इस दृश्य को प्रदर्शित करने के लिए तैयार हो जाते हैं, उदाहरण के लिए ऐप के प्रवेश बिंदु में, हम एक बना सकते हैं इकट्ठा करना। यह आवेदन शुरू करने के साथ-साथ प्रारंभिक अवस्था को निर्दिष्ट करके किया जा सकता है रिड्यूसर जो एप्लिकेशन को शक्ति देगा:

import ComposableArchitecture

@main
struct MyApp: App {
  var body: some Scene {
    WindowGroup {
      FeatureView(
        store: Store(initialState: Feature.State()) {
          Feature()
        }
      )
    }
  }
}

और यह स्क्रीन पर कुछ खेलने के लिए पर्याप्त है। यह निश्चित रूप से कुछ और है यदि आप इसे वैनिला स्विफ्टयूआई तरीके से करना चाहते हैं, तो यह कदम है, लेकिन इसके कुछ लाभ हैं। यह देता है हमें कुछ अवलोकनीय तर्कों में बिखरे हुए तर्क के बजाय, राज्य उत्परिवर्तनों को लागू करने के लिए एक सुसंगत तरीका है ऑब्जेक्ट्स और यूआई घटकों के विभिन्न एक्शन क्लोजर में। यह हमें एक संक्षिप्त तरीका भी देता है दुष्प्रभाव व्यक्त करना। और हम बिना प्रभाव के इस तर्क का तुरंत परीक्षण कर सकते हैं बहुत अधिक अतिरिक्त कार्य करना।

टेस्टिंग

परीक्षण के बारे में अधिक गहन जानकारी के लिए समर्पित [परीक्षण] testing-article लेख देखें।

परीक्षण के लिए एक टेस्टस्टोर का उपयोग करें, जिसे स्टोर के समान जानकारी के साथ बनाया जा सकता है, लेकिन यह आपको यह दावा करने की अनुमति देने के लिए अतिरिक्त काम करता है कि कार्रवाई भेजे जाने पर आपकी सुविधा कैसे विकसित होती है:

@MainActor
func testFeature() async {
  let store = TestStore(initialState: Feature.State()) {
    Feature()
  }
}

एक बार परीक्षण स्टोर बन जाने के बाद हम इसका उपयोग चरणों के संपूर्ण उपयोगकर्ता प्रवाह का दावा करने के लिए कर सकते हैं। जिस तरह से हर कदम पर हमें यह साबित करने की जरूरत है कि राज्य ने हमारी अपेक्षा को बदल दिया है। उदाहरण के लिए, हम कर सकते हैं वेतन वृद्धि और कमी बटनों पर टैप करने के उपयोगकर्ता प्रवाह का अनुकरण करें:

// Test that tapping on the increment/decrement buttons changes the count
await store.send(.incrementButtonTapped) {
  $0.count = 1
}
await store.send(.decrementButtonTapped) {
  $0.count = 0
}

इसके अलावा, यदि कोई कदम किसी प्रभाव को निष्पादित करता है, जो डेटा को स्टोर में वापस फीड करता है, तो हमें अवश्य करना चाहिए उस पर जोर देना। उदाहरण के लिए, यदि हम उस तथ्य बटन पर टैप करने वाले उपयोगकर्ता का अनुकरण करते हैं जिसकी हम अपेक्षा करते हैं तथ्य के साथ एक तथ्य प्रतिक्रिया वापस प्राप्त करें, जो तब अलर्ट दिखाने का कारण बनता है:

await store.send(.numberFactButtonTapped)

await store.receive(.numberFactResponse(.success(???))) {
  $0.numberFactAlert = ???
}

हालाँकि, हम कैसे जानते हैं कि कौन सा तथ्य हमें वापस भेजा जा रहा है?

वर्तमान में हमारा रेड्यूसर एक ऐसे प्रभाव का उपयोग कर रहा है जो एपीआई सर्वर को हिट करने के लिए वास्तविक दुनिया में पहुंचता है, और इसका मतलब है कि हमारे पास इसके व्यवहार को नियंत्रित करने का कोई तरीका नहीं है। हम अपने इंटरनेट की सनक पर हैं इस परीक्षण को लिखने के लिए कनेक्टिविटी और एपीआई सर्वर की उपलब्धता।

यह बेहतर होगा कि इस निर्भरता को रिड्यूसर को पास किया जाए ताकि हम लाइव का उपयोग कर सकें डिवाइस पर एप्लिकेशन चलाते समय निर्भरता, लेकिन परीक्षणों के लिए नकली निर्भरता का उपयोग करें। हम कर सकते हैं इसे फीचर रिड्यूसर में एक संपत्ति जोड़कर करें:

struct Feature: ReducerProtocol {
  let numberFact: (Int) async throws -> String}

तब हम इसे कम कार्यान्वयन में उपयोग कर सकते हैं:

case .numberFactButtonTapped:
  return .run { [count = state.count] send in 
    await send(
      .numberFactResponse(TaskResult { try await self.numberFact(count) })
    )
  }

और आवेदन के प्रवेश बिंदु में हम वास्तव में निर्भरता का एक संस्करण प्रदान कर सकते हैं वास्तविक विश्व एपीआई सर्वर के साथ इंटरैक्ट करता है:

@main
struct MyApp: App {
  var body: some Scene {
    FeatureView(
      store: Store(
        initialState: Feature.State(),
        reducer: Feature(
          numberFact: { number in
            let (data, _) = try await URLSession.shared
              .data(from: .init(string: "http://numbersapi.com/\(number)")!)
            return String(decoding: data, as: UTF8.self)
          }
        )
      )
    )
  }
}

लेकिन परीक्षणों में हम एक नकली निर्भरता का उपयोग कर सकते हैं जो तुरंत एक नियतात्मक, अनुमानित रिटर्न देता है तथ्य:

@MainActor
func testFeature() async {
  let store = TestStore(initialState: Feature.State()) {
    Feature(numberFact: { "\($0) is a good number Brent" })
  }
}

उस थोड़े से अग्रिम कार्य के साथ हम उपयोगकर्ता पर टैप करके अनुकरण करके परीक्षण पूरा कर सकते हैं तथ्य बटन, अलर्ट ट्रिगर करने के लिए निर्भरता से प्रतिक्रिया प्राप्त करना और फिर खारिज करना चेतावनी:

await store.send(.numberFactButtonTapped)

await store.receive(.numberFactResponse(.success("0 is a good number Brent"))) {
  $0.numberFactAlert = "0 is a good number Brent"
}

await store.send(.factAlertDismissed) {
  $0.numberFactAlert = nil
}

हम अपने आवेदन में नंबरफैक्ट निर्भरता का उपयोग करने के एर्गोनॉमिक्स में भी सुधार कर सकते हैं। ऊपर एप्लिकेशन कई सुविधाओं में विकसित हो सकता है, और उनमें से कुछ सुविधाओं तक पहुंच की आवश्यकता भी हो सकती है करने के लिए numberFact, और स्पष्ट रूप से इसे सभी परतों के माध्यम से पारित करना कष्टप्रद हो सकता है। एक प्रक्रिया होती है आप लाइब्रेरी के साथ "रजिस्टर" निर्भरताओं का अनुसरण कर सकते हैं, जिससे वे किसी को भी तुरंत उपलब्ध हो सकें आवेदन में परत।

निर्भरता प्रबंधन पर अधिक गहन जानकारी के लिए समर्पित [निर्भरता] dependencies-article लेख देखें।

हम संख्या तथ्य की कार्यक्षमता को एक नए प्रकार में लपेटकर शुरू कर सकते हैं:

struct NumberFactClient {
  var fetch: (Int) async throws -> String
}

और फिर उस प्रकार को क्लाइंट के अनुरूप बनाकर निर्भरता प्रबंधन प्रणाली के साथ पंजीकृत करना DependencyKey प्रोटोकॉल, जिसके लिए आपको चलाने के दौरान उपयोग करने के लिए लाइव मान निर्दिष्ट करने की आवश्यकता होती है सिमुलेटर या उपकरणों में आवेदन:

extension NumberFactClient: DependencyKey {
  static let liveValue = Self(
    fetch: { number in
      let (data, _) = try await URLSession.shared
        .data(from: .init(string: "http://numbersapi.com/\(number)")!)
      return String(decoding: data, as: UTF8.self)
    }
  )
}

extension DependencyValues {
  var numberFact: NumberFactClient {
    get { self[NumberFactClient.self] }
    set { self[NumberFactClient.self] = newValue }
  }
}

उस थोड़े से अग्रिम कार्य के साथ आप तुरंत निर्भरता का उपयोग करना शुरू कर सकते हैं @Dependency संपत्ति आवरण का उपयोग करके कोई सुविधा:

 struct Feature: ReducerProtocol {
-  let numberFact: (Int) async throws -> String
+  @Dependency(\.numberFact) var numberFact-  try await self.numberFact(count)
+  try await self.numberFact.fetch(count)
 }

यह कोड ठीक वैसे ही काम करता है जैसा उसने पहले किया था, लेकिन अब आपको स्पष्ट रूप से डिपेंडेंसी पास करने की आवश्यकता नहीं है फीचर के रेड्यूसर का निर्माण करते समय। ऐप को पूर्वावलोकन में चलाते समय, सिम्युलेटर या a डिवाइस, लाइव निर्भरता रेड्यूसर को प्रदान की जाएगी, और परीक्षणों में परीक्षण निर्भरता होगी प्रदान किया।

इसका मतलब है कि आवेदन के प्रवेश बिंदु को अब निर्भरताओं का निर्माण करने की आवश्यकता नहीं है:

@main
struct MyApp: App {
  var body: some Scene {
    FeatureView(
      store: Store(initialState: Feature.State()) {
        Feature()
      }
    )
  }
}

और परीक्षण स्टोर का निर्माण बिना किसी निर्भरता को निर्दिष्ट किए किया जा सकता है, लेकिन आप अभी भी कर सकते हैं परीक्षण के उद्देश्य के लिए आपको आवश्यक किसी भी निर्भरता को ओवरराइड करें:

let store = TestStore(initialState: Feature.State()) {
  Feature()
} withDependencies: {
  $0.numberFact.fetch = { "\($0) is a good number Brent" }
}

यह कंपोज़ेबल आर्किटेक्चर में एक फीचर के निर्माण और परीक्षण की मूल बातें हैं। वहाँ हैं बहुत और चीजों का पता लगाया जाना है, जैसे रचना, प्रतिरूपकता, अनुकूलनशीलता और जटिल प्रभाव। उदाहरण निर्देशिका में और अधिक देखने के लिए एक्सप्लोर करने के लिए परियोजनाओं का एक समूह है उन्नत उपयोग।

प्रलेखन

रिलीज और main के लिए दस्तावेज यहां उपलब्ध हैं

Other versions

दस्तावेज़ीकरण में ऐसे कई लेख हैं जो आपके और अधिक हो जाने पर आपको मददगार लग सकते हैं लाइब्रेरी के साथ सहज:

समुदाय

यदि आप कंपोज़ेबल आर्किटेक्चर पर चर्चा करना चाहते हैं या इसे हल करने के तरीके के बारे में कोई प्रश्न पूछना चाहते हैं एक विशेष समस्या, ऐसे कई स्थान हैं जिन पर आप साथी के साथ चर्चा कर सकते हैं प्वाइंट-फ्री उत्साही:

इंस्टालेशन

आप किसी Xcode प्रोजेक्ट को पैकेज डिपेंडेंसी के रूप में जोड़कर कंपोज़ेबल आर्किटेक्चर जोड़ सकते हैं।

  1. File मेन्यू से, Add Packages... चुनें
  2. पैकेज में "https://github.com/pointfreeco/swift-composable-architecture" दर्ज करें रिपॉजिटरी URL टेक्स्ट फ़ील्ड
  3. इस पर निर्भर करता है कि आपकी परियोजना कैसे संरचित है:
    • यदि आपके पास एक एकल एप्लिकेशन लक्ष्य है जिसे लाइब्रेरी तक पहुंच की आवश्यकता है, तो जोड़ें ComposableArchitecture सीधे आपके ऐप्लिकेशन पर|
    • यदि आप इस लाइब्रेरी का उपयोग कई Xcode लक्ष्यों से करना चाहते हैं, या Xcode लक्ष्य और SPM को मिला सकते हैं लक्ष्य, आपको एक साझा ढांचा बनाना होगा जो कि ComposableArchitecture और पर निर्भर करता है फिर अपने सभी लक्ष्यों में उस ढांचे पर निर्भर रहें। इसके उदाहरण के लिए, देखें Tic-Tac-Toe डेमो एप्लिकेशन, जो बहुत सारी विशेषताओं को विभाजित करता है tic-tac-toe Swift का उपयोग करके इस तरह से मॉड्यूल और स्थिर लाइब्रेरी का उपभोग करता है पैकेट

अनुवाद

The following translations of this README have been contributed by members of the community:

यदि आप अनुवाद में योगदान देना चाहते हैं, तो कृपया open a PR with a link to a Gist!

सामान्य प्रश्न

  • कंपोज़ेबल आर्किटेक्चर की तुलना एल्म, रेडक्स और अन्य से कैसे की जाती है?

    उत्तर देखने के लिए विस्तृत करें कंपोज़ेबल आर्किटेक्चर (टीसीए) एल्म द्वारा लोकप्रिय विचारों की नींव पर बनाया गया है आर्किटेक्चर (TEA) और रेडक्स, लेकिन स्विफ्ट भाषा और एप्पल की भाषा में घर जैसा महसूस कराया मंच।

    कुछ मायनों में टीसीए अन्य लाइब्रेरीों की तुलना में थोड़ा अधिक स्वच्छंद है। उदाहरण के लिए, Redux है साइड इफेक्ट्स को कैसे अंजाम दिया जाता है, इसके बारे में निर्देशात्मक नहीं है, लेकिन टीसीए को सभी साइड इफेक्ट्स की आवश्यकता होती है प्रभाव प्रकार में मॉडलिंग की और रेड्यूसर से वापस आ गया।

    अन्य तरीकों से टीसीए अन्य लाइब्रेरीों की तुलना में थोड़ा अधिक ढीला है। उदाहरण के लिए, एल्म क्या नियंत्रित करता है Cmd प्रकार के माध्यम से विभिन्न प्रकार के प्रभाव पैदा किए जा सकते हैं, लेकिन TCA किसी भी प्रकार के एस्केप हैच की अनुमति देता है प्रभावी होने के बाद से प्रभाव कंबाइन प्रकाशक प्रोटोकॉल के अनुरूप है।

    और फिर कुछ ऐसी चीजें हैं जिन्हें TCA अत्यधिक प्राथमिकता देता है जो फोकस के बिंदु नहीं हैं Redux, Elm, या अधिकांश अन्य लाइब्रेरी। उदाहरण के लिए, रचना TCA का बहुत महत्वपूर्ण पहलू है, जो बड़ी सुविधाओं को छोटी इकाइयों में तोड़ने की प्रक्रिया है जिसे चिपकाया जा सकता है साथ में। यह रेड्यूसर बिल्डरों और ऑपरेटरों जैसे स्कोप के साथ पूरा किया जाता है, और इसमें सहायता करता है एक बेहतर-पृथक कोड आधार और बेहतर के लिए जटिल सुविधाओं के साथ-साथ मॉड्यूलरीकरण को संभालना संकलन समय।

श्रेय और धन्यवाद

निम्नलिखित लोगों ने लाइब्रेरी के प्रारंभिक चरण में प्रतिक्रिया दी और लाइब्रेरी बनाने में मदद की यह आज क्या है:

पॉल कोल्टन, कान डेडियोग्लू, मैट डाइफहाउस, जोसेफ डोलेजल, इमांटास, मैथ्यू जॉनसन, जॉर्ज कैमाकास, निकिता लियोनोव, क्रिस्टोफर लिसियो, जेफरी मैको, एलेजांद्रो मार्टिनेज, शाई मिशाली, विलिस प्लमर, साइमन-पियरे रॉय, जस्टिन प्राइस, स्वेन ए. श्मिट, काइल शेरमेन, पेट्र सिमा, जसदेव सिंह, मैक्सिम स्मिर्नोव, रयान स्टोन, डैनियल हॉलिस टवारेस, और सभी [प्वाइंट-फ्री] pointfreeco सदस्य 😁।

[क्रिस लिस्सियो] (https://twitter.com/liscio) को विशेष धन्यवाद जिन्होंने हमें कई अजीबोगरीब काम करने में मदद की SwiftUI विचित्रता दिखाता है और अंतिम API को परिशोधित करने में मदद करता है।

और शाई मिशाली और को धन्यवाद CombineCommunity प्रोजेक्ट, जिससे हमने लिया Publishers.Create का उनका कार्यान्वयन, जिसका उपयोग हम ब्रिज प्रतिनिधि की मदद करने के लिए प्रभाव में करते हैं और कॉलबैक-आधारित एपीआई, तीसरे पक्ष के ढांचे के साथ इंटरफेस करना बहुत आसान बनाता है।

अन्य लाइब्रेरी

कंपोज़ेबल आर्किटेक्चर अन्य लाइब्रेरी द्वारा शुरू किए गए विचारों की नींव पर बनाया गया था विशेष रूप से Elm और Redux

स्विफ्ट और आईओएस समुदाय में कई आर्किटेक्चर लाइब्रेरी भी हैं। इनमें से प्रत्येक के पास है प्राथमिकताओं और ट्रेड-ऑफ़ का उनका अपना सेट जो कंपोज़ेबल आर्किटेक्चर से अलग है।

लाइसेंस

यह लाइब्रेरी एमआईटी लाइसेंस के तहत जारी किया गया है। विवरण के लिए [लाइसेंस] (LICENSE) देखें।

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment