Starter kit for Core architecture.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Core.xcodeproj
Core Simplify async actions Jul 20, 2017
CoreTests
iOS Example Tests
iOS Example
.gitignore
.swift-version
.travis.yml
Core-Diagram.png
CoreArchitecture.podspec
LICENSE.txt
README.md

README.md

Core

Carthage CocoaPods CI Status Platform Language License

Core helps you design applications in a way that the app flow is driven by business layer, instead of UI layer. It also promotes unidirectional data flow between components for consistency, high testability and powerful debugging.

Related Article: Architecting iOS Apps with "Core"

Design

Class Diagram

  • Core is simply a box that represents our app.
  • Components are our features.
  • Actions are the changes that happen on the system.
  • Subscribers can be anything. It can be a console app. It can be an iOS app. It can be our test suite.

Core can be seen as a Redux, Flux and MVVM hybrid.

Main differences between Core and Redux:

  • Redux is static. It expects you to define a big fat structure that expresses the app state in compile time. This can be challenging if you have reusable controllers that you present here and there a number of times. Especially in cases where your application flow is altered by server responses, you cannot easily define your app state in compile time without hacking the architecture. Core is dynamic. You only need to define the state and actions for the component you are working on. Transition between components is handled dynamically.

  • In Redux, there is no standard way to implement navigation between components. With Core, you get native navigation support.

  • Redux focuses on application state, whereas Core focuses on isolated component state. In this regard, I find it easier to work in isolation on one component rather than getting lost in huge application state.

  • In Redux, since the state is global, it’s easy to forget to do state clean-up when a screen is popped from the navigation stack. In Core, since every component stores its own state, when you remove a component from the tree, state gets disposed along with it. This is handled internally by navigation mechanism.

Implementation

I'll follow the tradition and start with countdown example.

State:

struct CountdownState: State {
  var count: UInt
}

Actions:

enum CountdownAction: Action {
  case tick
}

Component:

class CountdownComponent: Component<CountdownState> {
  
  func process(action: Action) {
    guard let action = action as? LoginAction else { return }
    switch action {
    case .tick:
      tick()
    }
  }
  
  private func tick() {
    var state = state 
    state.count = state.count - 1
    if state.count == 0 {
      let nextComponent = ResultComponent()
      let navigation = BasicNavigation.push(nextComponent, from: self)
      commit(state, navigation)
    } else {
      commit(state)
    }
  }
}

More complex examples:

Installation

Using CocoaPods

Add the following line to your Podfile:

pod 'CoreArchitecture'

Using Carthage

Add the following line to your Cartfile:

github "gokselkoksal/Core"

Manually

Drag and drop Sources folder to your project.

It's highly recommended to use a dependency manager like CocoaPods or Carthage.

Alternatives

You can also check out ReSwift, Reactor or Dispatch for pure Redux and Flux implementations for Swift.

License

Core is available under the MIT license.