SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.

Overview

Articles related to this project


Clean Architecture for SwiftUI + Combine

A demo project showcasing the setup of the SwiftUI app with Clean Architecture.

The app uses the restcountries.eu REST API to show the list of countries and details about them.

Check out mvvm branch for the MVVM revision of the same app.

For the example of handling the authentication state in the app, you can refer to my other tiny project that harnesses the locks and keys principle for solving this problem.

platforms Build Status codecov codebeat badge

Diagram

Key features

  • Vanilla SwiftUI + Combine implementation
  • Decoupled Presentation, Business Logic, and Data Access layers
  • Full test coverage, including the UI (thanks to the ViewInspector)
  • Redux-like centralized AppState as the single source of truth
  • Data persistence with CoreData
  • Native SwiftUI dependency injection
  • Programmatic navigation. Push notifications with deep link
  • Simple yet flexible networking layer built on Generics
  • Handling of the system events (such as didBecomeActive, willResignActive)
  • Built with SOLID, DRY, KISS, YAGNI in mind
  • Designed for scalability. It can be used as a reference for building large production apps

Architecture overview

Diagram

Presentation Layer

SwiftUI views that contain no business logic and are a function of the state.

Side effects are triggered by the user's actions (such as a tap on a button) or view lifecycle event onAppear and are forwarded to the Interactors.

State and business logic layer (AppState + Interactors) are navitely injected into the view hierarchy with @Environment.

Business Logic Layer

Business Logic Layer is represented by Interactors.

Interactors receive requests to perform work, such as obtaining data from an external source or making computations, but they never return data back directly.

Instead, they forward the result to the AppState or to a Binding. The latter is used when the result of work (the data) is used locally by one View and does not belong to the AppState.

Previously, this app did not use CoreData for persistence, and all loaded data were stored in the AppState.

With the persistence layer in place we have a choice - either to load the DB content onto the AppState, or serve the data from Interactors on an on-demand basis through Binding.

The first option suits best when you don't have a lot of data, for example, when you just store the last used login email in the UserDefaults. Then, the corresponding string value can just be loaded onto the AppState at launch and updated by the Interactor when the user changes the input.

The second option is better when you have massive amounts of data and introduce a fully-fledged database for storing it locally.

Data Access Layer

Data Access Layer is represented by Repositories.

Repositories provide asynchronous API (Publisher from Combine) for making CRUD operations on the backend or a local database. They don't contain business logic, neither do they mutate the AppState. Repositories are accessible and used only by the Interactors.


Twitter blog venmo

Issues
  • Question about reacting to state change

    Question about reacting to state change

    Hi!

    First of all, a very awesome project and article on clean architecture with SwiftUI.

    I have a question though.

    You say Instead, they forward the result to the AppState or to a Binding. The latter is used when the result of work (the data) is used locally by one View and does not belong to the AppState.

    For the first case, I can subscribe to any data change in Store by using something like routingUpdate and then .onReceive(routingUpdate) { _ in }. But I am a bit struggling with the latter case - I pass a binding to an Interactor when the data is only applicable to one view. I modify the binding in that Interactor, my views react to the change, but I also want to subscribe that change in the view and do some additional actions/interactions. How would I achieve that?

    opened by NeverwinterMoon 16
  • [Question] How would you react to state changes in view

    [Question] How would you react to state changes in view

    Hi there !

    At first thank you for providing this repository and your related blog posts. I enjoyed reading them and they helped me a lot.

    But I have a question about reacting to @State changes in Views in this architecture.


    For example I have the following case in my application:

    I have a view which displays a list of tasks for a specific date interval. It has your dependency injection container injected:

    @Environment(\.injected) private var injected: DIContainer
    @State private var dateInterval: DateInterval = DateInterval(start: Date().startOfWeek ?? Date(), end: Date().endOfWeek ?? Date())
    

    Initially the data is fetched with a method that looks like this:

    func fetch() {
        injected.interactors.myInteractor
            .fetchData(range: self.dateInterval)
            .store(in: cancelBag)
    }
    

    The view has a child which accepts a binding to the dateInterval and is able to change it:

     WeeksTaskGraph(dateInterval: self.$dateInterval, tasks: tasks)
    

    Now I need to refetch data when the binding changes. So basically I would need to run the fetch method again when the dateInterval changes. I tried to create an ObservableObject ViewModel class for the view, for encapsulating this kind of functionality. It looks roughly like this:

    class DateIntervalModel: ObservableObject {
        
        private let cancelBag = CancelBag()
        
        @Environment(\.injected) private var injected: DIContainer
        
        @Published var dateInterval: DateInterval = DateInterval(start: Date().startOfWeek ?? Date(), end: Date().endOfWeek ?? Date()) {
            didSet {
                print("Date interval changed")
                 injected.interactors.myInteractor.fetchData(range: self.dateInterval)
                    .store(in: cancelBag)
            }
        }
    }
    

    But as seen this class would then need access to the @EnvironmentObject which I could not find a solution how to achieve that - since it is not part of the view hierarchy.

    Do you maybe have an approach or a suggestion how this can be achieved with the clean architecture ?

    Any help is appreciated ! If this is the wrong place for asking this kind of questions feel free to close the issue or tell me so.

    opened by alexanderwe 13
  • Examples of custom full-screen transition animations based on Routing

    Examples of custom full-screen transition animations based on Routing

    Would you consider adding an example of full-screen view transition animations based on Routing to this project? Something where both - the new view and the previous view - would have different transition animations. Say, previous view scales down and the new view slides in.

    opened by NeverwinterMoon 11
  • Access contents of lazylist

    Access contents of lazylist

    Awesome template for clean architecture!

    I've the below combine pipeline which is the opposite of way you're handling data in this template; In most real world scenarios;

    • data is first fetched from the web
    • then stored in the db
    • if fetching from web fails
    • load from db
    func refreshCards(id: String) -> AnyPublisher<Void, Error> {
        var cards: [Card] = []
        return gateway
        .listCards(customerID: id)
        .map {
            response in
            response.cards.forEach {
                cards.append(Card(protoObject: $0)!)
            }
            return cards
        }
    
        .catch {
            err in
            // must return a Publisher
            repository.cards()
        }
    
        .flatMap {
            [repository] in
            repository.store(cards: $0) // Cannot convert value of type 'LazyList<Card>' to expected argument type '[Card]'
        }
    
        .eraseToAnyPublisher()
    }
    

    repository.store(cards: ) accepts an array of cards - [Card] - how can I unpack LazyList and turn it into an array?

    opened by moh-abk 5
  • @Enviroment vs @EnviromentObject

    @Enviroment vs @EnviromentObject

    I am pretty new to iOS development and I don't have background of Javascript and UIKit. I am learning SwiftUI directly.

    Why did you used @Enviroment and not @EnviromentObject in your project? Can you please add comments in your code so it will more useful for beginners like me.

    Thanks for creating this project and post related to it. It was very helpful and appreciated :)

    opened by ramtest55 5
  • App doesn't build

    App doesn't build

    /UnitTests/Mocks/MockedInteractors.swift:38:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'loadCountryDetails(_:)' (identifier_name)

    /UnitTests/Mocks/MockedInteractors.swift:63:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'loadImage(_:)' (identifier_name)

    /UnitTests/Mocks/MockedWebRepositories.swift:25:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'loadCountryDetails(_:)' (identifier_name)

    /UnitTests/Mocks/MockedWebRepositories.swift:48:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'loadImage(_:)' (identifier_name)

    /CountriesSwiftUI/Repositories/CountriesWebRepository.swift:49:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'countryDetails(_:)' (identifier_name)

    /CountriesSwiftUI/Utilities/APICall.swift:20:10: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'httpCode(_:)' (identifier_name)

    /CountriesSwiftUI/System/SystemEventsHandler.swift:80:14: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'showCountryFlag(alpha3Code:)' (identifier_name)

    /CountriesSwiftUI/Utilities/Loadable.swift:14:10: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'isLoading(last:)' (identifier_name)

    /CountriesSwiftUI/Utilities/Loadable.swift:15:10: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'loaded(_:)' (identifier_name)

    /CountriesSwiftUI/Utilities/Loadable.swift:16:10: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'failed(_:)' (identifier_name)

    opened by GJNilsen 5
  • Cannot connect to REST API

    Cannot connect to REST API

    Hey,

    fist off thanks for this insightful repository and article!

    When cloning the repository and trying to run it, the application can not connect to the REST API restcountries.eu. Trying to access it via a browser redirects to countrylayer.com. I'm not sure what happened with the API or if it is something that just temporarily happened to me.

    Kind regards

    opened by stef-t 4
  • cancel bag is not needed

    cancel bag is not needed

    AnyCancellable is doing cancel on deinit, it called RAII pattern: https://developer.apple.com/documentation/combine/anycancellable

    An AnyCancellable instance automatically calls cancel() when deinitialized
    

    No need to call explicit cancel() on items. CancelBag looks like its not needed. It will cleanup a lot of code

    opened by sisoje 4
  • Question: presenting another same view in view hierarchy

    Question: presenting another same view in view hierarchy

    Hello Alex,

    Thank you for your architecture example and articles, they are awesome and help me a lot to understand how to work with SwiftUI.

    I would like to ask you about more complex navigation in the example. For example, the application has to show CountryDetails from ModalDetailsView. I tried to implement this in fork https://github.com/iomark/clean-architecture-swiftui/tree/test/same_view . As you can see it leads to weird effects. Could you advise how to resolve similar use cases related to using a view that already is presented in view hierarchy? As I understand the application routing state should resolve it in some way.

    opened by iomark 4
  • Consider turning this project into a tutorial

    Consider turning this project into a tutorial

    Hey there,

    I am a novice in programming, and I struggle grasping architectures very much. That SwiftUI / Combine are so new does not help a bit, as the dust is definitely not settled yet, and seems like very few really understand how to design with new frameworks.

    This project (just as your posts btw) reads very easily, yet I still struggle understanding the core 'why's of the architecture, not to say that I cannot see the whole picture well.

    If turned into a tutorial with detailed explanations and rationales describing the architecture, this becomes a goto place to learn how SwiftUI / Combine apps are designed. By tutorial I mean something akin to Apple's (unfortunately very non-informative) multi-step tutorial residing on /tutorials page.

    This seems like not an easy task, but maybe other experienced devs can join this initiative.

    Thanks!

    opened by shengchalover 4
  • Question: why `case .isLoading` is not called even we got `.isLoading` on didSet?

    Question: why `case .isLoading` is not called even we got `.isLoading` on didSet?

    Hi, thanks for sharing and committing such a great project.

    While using your architecture, I found that the the scope below is not always called:

    https://github.com/nalexn/clean-architecture-swiftui/blob/9f2a98a7146f2e28fe44c53d3b9f20620f203baa/CountriesSwiftUI/UI/Screens/CountryDetails/CountryDetails.swift#L28-L29

    even though you did setIsLoading at below:

    https://github.com/nalexn/clean-architecture-swiftui/blob/9f2a98a7146f2e28fe44c53d3b9f20620f203baa/CountriesSwiftUI/Services/CountriesService.swift#L68

    Is this behavior intended?

    What I'm expecting is that the loading view will be shown if you enter the view every time. But, it's not.


    I've also checked actual value with

            @Published var details: Loadable<Country.Details> {
                willSet{
                    print("willSet (\(details) -> \(newValue))")
                }
                didSet {
                    print("didSet (\(oldValue) -> \(details))")
                }
            }
    

    then I got

    willSet (notRequested -> isLoading(last: nil, cancelBag: CountriesSwiftUI.CancelBag))
    didSet (notRequested -> isLoading(last: nil, cancelBag: CountriesSwiftUI.CancelBag))
    willSet (isLoading(last: nil, cancelBag: CountriesSwiftUI.CancelBag) -> loaded(CountriesSwiftUI.Country.Details(...)
    didSet (isLoading(last: nil, cancelBag: CountriesSwiftUI.CancelBag) -> loaded(CountriesSwiftUI.Country.Details(...)
    

    so I expected CountryDetails.swift#L29 to be run, but it's not.

    It may be very basic behavior or just an overlook of me but I appreciate anyone's help.

    opened by mitolog 1
  • Fixing readme typo

    Fixing readme typo

    This PR fixed the typo from navitely to natively.

    opened by schinj 0
  • The reversed data flow from the standard SwiftUI views back to the AppState

    The reversed data flow from the standard SwiftUI views back to the AppState

    Hi @nalexn

    I like what you did with this clean-architecture approach, I read some of your articles related to SwiftUI State and I saw the below implementation of reversing the data flow from views to AppState:

    extension Binding where Value: Equatable {
        func dispatched<State>(to state: Store<State>,
                               _ keyPath: WritableKeyPath<State, Value>) -> Self {
            return onSet { state[keyPath] = $0 }
        }
    }
    
    extension Binding {
        typealias ValueClosure = (Value) -> Void
        
        func onSet(_ perform: @escaping ValueClosure) -> Self {
            return .init(get: {
                self.wrappedValue
            }, set: {
                self.wrappedValue = $0
                perform($0)
            })
        }
    }
    

    where you will use it like this:

    @State var routingState: Routing = .init()
    private var routingBinding: Binding<Routing> {
        $routingState.dispatched(to: injected.appState, \.routing.home)
    }
    

    It works in terms of updating the AppState, but if we look at the implementation of dispatched/onSet function we notice that it wraps the Value in a new Binding instance and this will cause the view to rerender again while it's not needed, I wanna check if you are aware about this case or maybe I didn't understand the idea properly.

    I can show you and example if needed.

    opened by mohammad19991 8
  • Question: clean architecture, boundaries and reactive frameworks

    Question: clean architecture, boundaries and reactive frameworks

    Hello !

    I just discovered your work through this breakdown https://nalexn.github.io/uikit-switfui/ and followed my way up to here :). First of all thank you for this very well articulated article. While reading it, I was thinking "yes.. yes... oh yeah ! been there, see what you mean... totally agree and very-well phrased... this guy is on point !" I especially loved this part: "Nevertheless, there is a heck of a lot of business logic running on modern mobile apps, but that logic is different. It’s just more focused on the presentation rather than on the core rules the business runs on.

    This means we need to do a better job at decoupling that presentation-related business logic from the specifics of the UI framework we’re using."

    Still, one thing "surprised"/"puzzled" me a bit, regarding clean architecture. On one hand you seem very prone to raise a strict boundary between the presentation layer & the "domain/core layer" (even for simple use cases that fetch data from an abstract repo), pushing UIKit / SwiftUI specificities to the outer limits, where they belong. Basically, if it's a framework then I don't want it to be polluting the core of my app. Yet, you don't seem reluctant or bothered at all to "let" a reactive programming framework (be it an Apple "stamped" one like Combine or worse, a third-party one like Rx) going through pretty much everything, from data fetching to use-cases to presentation to ui. I'm sure this is a totally deliberate choice so I'd be glad if you can share some thoughts on that. For instance, did you ever considered preserving your core as strictly 100% vanilla Swift and plug the rest of the system through reactive adapters to this core ? Do you feel it's not worth it ? In a fictive scenario where Apple's Combine isn't quite "bridgeable" to Rx, because their respective philosophy differs a bit too much, this could be very damaging, don't you think ?

    opened by jrmybrault 2
  • Tapping flag results in error

    Tapping flag results in error

    When running the app, if tap on any flag in the country detail, you get the following error: Thread 1: Simultaneous accesses to 0x7f9ef2eae650, but modification requires exclusive access

    opened by johnrnyquist 3
  • ViewModels reinitialize after view changes

    ViewModels reinitialize after view changes

    First of all, thanks for all the work put onto this project. I'm building a project based off of this and it's looking really good, but I am encountering some issues that I explain below.

    To summarize:

    ViewA navigates to ViewB. To achieve this, I implement a NavigationLink(destination: ViewB(viewModel: ViewBViewModel())). When inside ViewB, some app state is modified, which ViewA receives with a onReceive. In the onReceive callback, ViewA makes some changes to its view like disabling a button. This causes ViewA to recalculate itself, which initializes ViewBViewModel again, losing all the changes, including all loaded data from the repository, leaving the user on ViewB with all Loadable set to .notRequested, and all viewModel state lost.

    This also happens if the app state is implemented through a EnvironmentObject. If I modify some environment object from ViewB that ViewA uses, ViewA recreates itself, losing all the state on ViewBViewModel.

    I am also having some issues related to this when navigating back from a view to its predecessor. In some cases, if I navigate from some view ViewA to other view ViewB, when dismissing ViewB, ViewA gets recalculated, which initializes ViewBViewModel again.

    Has anyone encountered this behaviour and came to a solution?

    opened by guillevc 1
  • How about making the example do modifications?

    How about making the example do modifications?

    This is an interesting model (I'm looking at the MVVM version)

    Would you be able to implement updates via the UI into CoreData? It looks like the sample implementation implements the read path. I'd be curious how the write path works, specifically:

    1. I'm curious how you would implement TextField updates (for example, to let the user change the name of a country). Simple implementations would bind the TextField to the View Model and then (maybe?) use a combine pipeline to write updates to the view model to the DB. How would you convert this to an action?
    2. I'm also curious how you would handle CoreData synchronizations from iCloud. How does this model detect changes coming from the user (user edits the country) and thus the change needs to flow to CoreData, vs a change that happens in CoreData (maybe they have the app loaded on another device and changed the country there) needing to update the UI. How would you handle conflicts in this model?

    Thank you for the cool work!

    opened by teemobean 1
  • Question: Accessing Loadable state outside CountriesList

    Question: Accessing Loadable state outside CountriesList

    Hi,

    Thanks for the awesome repository! It is a great source for beginners in IOS development to learn the basics of Architecture in SwiftUI Programming!

    I was wondering based on your current solution, how would you expose the current state of the loadable to the parent component? For example, you want to show something else in the parent as soon as the loadable in the child is finished loading.

    Thanks!

    opened by Cobrijani 4
  • Question: about your article of stranger-things-swiftui-state

    Question: about your article of stranger-things-swiftui-state

    Hi First of all, thank you I'm learning a lot about clean architecture for Swift UI from you

    stranger-things-swiftui-state in the "Clean Architecture for SwiftUI" article, "Coordinator is history" Section In this scenario,

    struct TestView: View {
    
        let publisher = PassthroughSubject<String, Never>()    // 1
        let publisher = CurrentValueSubject<String, Never>("") // 2
        
        var body: some View {
            MyView(publisher: publisher.eraseToAnyPublisher())
        }
    }
    

    Scenario 2 works differently.

    Here's my code.

    import SwiftUI
    
    @main
    struct TestSwiftUIApp: App {
        
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    
    import SwiftUI
    import Combine
    
    struct ContentView: View {
        let publisher = CurrentValueSubject<String, Never>("") // 2
        var body: some View {
            MyView(publisher: publisher.eraseToAnyPublisher())
        }
        
    }
    
    struct MyView: View {
        
        let publisher: AnyPublisher<String, Never>
        
        @State var text: String = ""
        @State var didAppear: Bool = false
        
        var body: some View {
            Text(text)
                .onAppear { self.didAppear = true }
                .onReceive(publisher) {
                    print("onReceive")
                    self.text = $0
                }
        }
    }
    

    image

    my answer is 1...

    also

    struct MyView: View {
        
        let publisher: AnyPublisher<String, Never>
        
        @State var text: String = ""
        @State var didAppear: Bool = false
        
        var body: some View {
            Text(text)
                .onAppear { self.didAppear = true
                    self.text = "abc"
                }
                .onReceive(publisher) {
                    print("onReceive")
                    self.text = $0
                }
        }
    }
    

    my answer is "abc"...

    image

    The result is different because of SwifttUI 2.0? or I'm missing something?

    Thanks

    opened by ChoiDongKyu96 2
Owner
Alexey Naumov
Designing software the ruthless way
Alexey Naumov
Spin aims to provide a versatile Feedback Loop implementation working with the three main reactive frameworks available in the Swift community (RxSwift, ReactiveSwift and Combine)

With the introduction of Combine and SwiftUI, we will face some transition periods in our code base. Our applications will use both Combine and a thir

Spinners 109 Nov 8, 2021
YARCH iOS Architecture

YARCH is an architecture pattern developed primarly for iOS applications. You can ask any questions in our telegram channel. Russian version of the re

Alfa Digital 187 Dec 22, 2021
A collection of iOS architectures - MVC, MVVM, MVVM+RxSwift, VIPER, RIBs and many others

ios-architecture WIP ?? ?? ?? ??️ Demystifying MVC, MVVM, VIPER, RIBs and many others A collection of simple one screen apps to showcase and discuss d

Pawel Krawiec 1.1k Jan 12, 2022
A holistic approach to iOS development, inspired by Redux and MVVM

Tempura is a holistic approach to iOS development, it borrows concepts from Redux (through Katana) and MVVM. Model your app state Define the actions t

Bending Spoons 649 Dec 30, 2021
A Swift 4.2 VIPER Module Boilerplate Generator with predefined functions and a BaseViewProtocol.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Are you new to VIPER Design Pattern? Want

Mohamad Kaakati 63 Nov 7, 2021
Calculate your Equated Monthly instalment (EMI) for Home loan, Housing loan, Car loan & Personal loan (Based on Uncle Bob's clean architecture approach and special thanks to http://clean-swift.com/clean-swift-ios-architecture)

![Language](https://img.shields.io/badge/language-Swift 3.0-orange.svg) Calculate your Equated Monthly instalment (EMI) for Home loan, Housing loan, C

Tirupati Balan 16 Aug 16, 2020
This repository contains a detailed sample app that implements VIPER architecture in iOS using libraries and frameworks like Alamofire, AlamofireImage, PKHUD, CoreData etc.

iOS Viper Architecture: Sample App This repository contains a detailed sample app that implements VIPER architecture using libraries and frameworks li

MindOrks 615 Jan 10, 2022
Simple sample of using the VIP (Clean Swift) architecture for iOS

MyAnimeList Simple sample of using the VIP (Clean Swift) architecture for iOS. ViewController: controls the event handling, view life cycle and displa

null 19 Dec 25, 2021
Simple sample of using the VIP (Clean Swift) architecture for iOS

MyAnimeList Simple sample of using the VIP (Clean Swift) architecture for iOS. ViewController: controls the event handling, view life cycle and displa

null 19 Dec 25, 2021
Sample iOS app demonstrating Coordinators, Dependency Injection, MVVM, Binding

iOS Sample App Sample iOS app written the way I write iOS apps because I cannot share the app I currently work on. Shown concepts Architecture concept

Igor Kulman 583 Jan 8, 2022
Runtime introspection and unit testing of SwiftUI views

ViewInspector ??️‍♂️ for SwiftUI ViewInspector is a library for unit testing SwiftUI views. It allows for traversing a view hierarchy at runtime provi

Alexey Naumov 1k Dec 25, 2021
JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box. It also allows you to migrate to any other persistence framework with minimal effort.

JustPersist JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box. It also allows you to migrate to

Just Eat 167 Jan 5, 2022
iOS Database Persistence Layer with SQLite, your next Persistence Layer!

pod "CTPersistance" CTPersistance is a sqlite wrapper which help you to handle with database. I'm still writing this document, you can check test case

Casa Taloyum 737 Nov 23, 2021
Example of Clean Architecture of iOS app using RxSwift

Clean architecture with RxSwift Contributions are welcome and highly appreciated!! You can do this by: opening an issue to discuss the current solutio

null 3.3k Jan 13, 2022
A Mac and iOS Playgrounds Unit Testing library based on Nimble.

Spry Spry is a Swift Playgrounds Unit Testing library based on Nimble. The best thing about Spry is that the API matches Nimble perfectly. Which means

Quick 328 Dec 22, 2021
PJFDataSource is a small library that provides a simple, clean architecture for your app to manage its data sources while providing a consistent user interface for common content states (i.e. loading, loaded, empty, and error).

PJFDataSource PJFDataSource is a small library that provides a simple, clean architecture for your app to manage its data sources while providing a co

Square 89 Apr 22, 2020
iOS app with TMDb Api. RxSwift, MVVM, Clean Architecture.

TVToday app TVToday es una app para iOS que consulta TVShows Usa la API TheMovieDb Desarrollo en iOS Swift 5 RxSwift, RxDataSources Cordinator Pattern

Jeans Ruiz 21 Dec 20, 2021
Compile-time safe Swift dependency injection framework

Needle is a dependency injection (DI) system for Swift. Unlike other DI frameworks, such as Cleanse, Swinject, Needle encourages hierarchical DI struc

Uber Open Source 1.1k Jan 11, 2022
Dependency Injection framework for Swift (iOS/macOS/Linux)

Declarative, easy-to-use and safe Dependency Injection framework for Swift (iOS/macOS/Linux) Features Dependency declaration via property wrappers or

Scribd 616 Jan 4, 2022
Dependency injection for iOS (Swift)

DITranquillity Tranquillity is a lightweight but powerful dependency injection library for swift. The name "Tranquillity" laid the foundation in the b

Ivlev Alexander 379 Jan 9, 2022
Dependency injection framework for Swift with iOS/macOS/Linux

Swinject Swinject is a lightweight dependency injection framework for Swift. Dependency injection (DI) is a software design pattern that implements In

null 5k Jan 4, 2022
Nonintrusive Objective-C Dependency Injection

Reliant Reliant is a Dependency Injection (DI) framework for Objective-C, both for OS X and iOS. Its goal is to make its use as simple as possible, wh

AppFoundry 53 Jun 29, 2021
Lightweight Swift Dependency Injection Framework

Cleanse - Swift Dependency Injection Cleanse is a dependency injection framework for Swift. It is designed from the ground-up with developer experienc

Square 1.7k Jan 14, 2022
Powerful dependency injection for Objective-C ✨✨ (https://PILGRIM.PH is the pure Swift successor to Typhoon!!)✨✨

Typhoon Powerful dependency injection for Cocoa and CocoaTouch. Lightweight, yet full-featured and super-easy to use. Pilgrim is a pure Swift successo

AppsQuick.ly 2.7k Dec 26, 2021
Easy dependency injection for storyboard segues

Perform Easy dependency injection for storyboard segues. import Perform // ... func tableView(_ tableView: UITableView, didSelectRowAt indexPath: NS

thoughtbot, inc. 278 Jul 20, 2021
A Coreader-like Dependency Injection μFramework

Corridor A Coreader-like Dependency Injection μFramework Table of Contents Why | Examples | Usage | Installation | Credits & License | Why In order to

symentis GmbH 57 May 9, 2020
Deli is an easy-to-use Dependency Injection(DI).

Deli is an easy-to-use Dependency Injection Container that creates DI containers with all required registrations and corresponding factories. Language

Jungwon An 130 Dec 12, 2021
Dependency Injection Framework for Swift, inspired by KOIN.

DIKit Dependency Injection Framework for Swift, inspired by KOIN. Basically an implementation of service-locator pattern, living within the applicatio

null 87 Nov 21, 2021