Core is a framework for making more reactive applications inspired by ReactorKit, Redux.
Core is Reactive independent Framework which means you can expand whatever you want to import such as Combine, RxSwift.
It's a very light weigthed and simple architecture, so you can either use CocoaPods or SPM to stay up to date, or just drag and drop into your project and go. Or you can look through it and roll your own.
CoreEngine is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'CoreEngine'
Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
To integrate SnapKit into your Xcode project using Swift Package Manager, add it to the dependencies value of your Package.swift
:
dependencies: [
.package(url: "https://github.com/sobabear/CoreEngine.git", .upToNextMajor(from: "1.1.0"))
]
Core Engine is insanely fast and light-weight compared to similar frameworks you can check details here CoreEngineBenchMark
See details on Example
// on ViewController
let label = UILabel()
let increaseButton = UIButton()
let decreaseButton = UIButton()
var core: MainCore = .init()
func increaseButtonTapped() {
self.core.action(.increase)
}
func decreaseButtonTapped() {
self.core.action(.decrease)
}
func multipleActions() {
self.core.action(.increase, .decrease)
}
func bind() {
core.$state.map(\.count)
.sink { [weak self] count in
self?.label.text = "\(count)"
}
.store(in: &subscription)
}
...
class MainCore: Core {
var subscription: Set<AnyCancellable> = .init()
enum Action: Equatable, Hashable {
case increase
case decrease
}
struct State: Equatable {
var count = 0
}
@Published var state: State = .init()
func reduce(state: State, action: Action) -> State {
var newState = state
switch action {
case .decrease:
newState.count -= 1
case .increase:
newState.count += 1
}
return newState
}
}
Not just simple core, but complex core is also supported. For example, Side Effect and Error handling. When it comes to those, you use AnyCore
.
It is not very different from Core, since AnyCore also conforms.
This method is defined in AnyCore and when you deal with side-effect generated publisher send into the function. Also you can handle every errors on the handleError(error: Error)
function
Here is an example of the AnyCore
class MainCore: AnyCore {
var subscription: Set<AnyCancellable> = .init()
enum Action {
case increase
case decrease
case jump(Int)
case setNumber(Int)
}
struct State {
var count = 0
}
@Published var state: State = .init()
@Published var tenGap: Int = 10
private let sessionService = SessionService()
init {
dispatch(effect: sessionService.randomUInt$().map(Action.setNumber))
}
func reduce(state: State, action: Action) -> State {
var newState = state
switch action {
case .increase:
newState.count += 1
case .decrease:
newState.count -= 1
case let .jump(value):
newState.count += value
case let .setNumber(value):
newState.count = value
}
return newState
}
func handleError(error: Error) {
if let errpr = error as? MyError {
//handle
}
}
func tenJumpAction() {
self.dispatch(effect: $tenGap.map(Action.jump))
}
}
class SessionService {
func randomUInt$() -> AnyPublisher<Int, Error> {
// blahblah
}
}
copy those code for RxSwift
import Foundation
import CoreEngine
import RxSwift
protocol RxCore: Core {
var disposeBag: DisposeBag { get set }
func mutate(effect: Observable<Action>)
func handleError(error: Error)
}
extension RxCore {
public func mutate(effect: Observable<Action>) {
effect
.subscribe(onNext: { [weak self] in
if let self {
self.state = self.reduce(state: self.state, action: $0)
}
}, onError: { [weak self] in
self?.handleError(error: $0)
})
.disposed(by: disposeBag)
}
public func handleError(error: Error) { }
}
@propertyWrapper
class ObservableProperty<Element>: ObservableType {
var wrappedValue: Element {
didSet {
subject.onNext(wrappedValue)
}
}
private let subject: BehaviorSubject<Element>
init(wrappedValue: Element) {
self.wrappedValue = wrappedValue
self.subject = BehaviorSubject<Element>(value: wrappedValue)
}
var projectedValue: Observable<Element> {
return subject.asObservable()
}
func subscribe<Observer>(_ observer: Observer) -> Disposable where Observer : ObserverType, Element == Observer.Element {
return subject.subscribe(observer)
}
}
stareta1202, stareta1202@gmail.com
CoreEngine is available under the MIT license. See the LICENSE file for more info.