Core 是一个用于构建更具响应式应用程序的框架,其灵感来源于 ReactorKit 和 Redux。
Core 是一个与 Reactive 无关的框架,这意味着你可以扩展任何你想导入的内容,例如 Combine、RxSwift。
它是一个非常轻量级且简单的架构,因此你可以使用 CocoaPods 或 SPM 来保持更新,或者直接拖放到你的项目中即可使用。或者你可以浏览代码并自行构建。
CoreEngine 可以通过 CocoaPods 获取。要安装它,只需将以下行添加到你的 Podfile
pod 'CoreEngine'
Swift Package Manager 是一个用于管理 Swift 代码分发的工具。它与 Swift 构建系统集成,以自动化下载、编译和链接依赖项的过程。
要使用 Swift Package Manager 将 SnapKit 集成到你的 Xcode 项目中,请将其添加到你的 Package.swift
文件的 dependencies 值中
dependencies: [
.package(url: "https://github.com/sobabear/CoreEngine.git", .upToNextMajor(from: "1.3.1"))
]
与类似的框架相比,Core Engine 异常快速且轻量,你可以在这里查看详细信息:CoreEngineBenchMark
虽然 CoreEngine 提供了传统的响应式方法和状态管理模式,但我们强烈推荐使用 AsyncCore 来进行现代、异步和更高效的状态处理。
AsyncCore 利用 Swift 的结构化并发和 async/await,提供了一种清晰直观的方式来管理状态更新、处理副作用,并使用 Swift 的 Actor 模型确保线程安全。
并发优先:为 Swift 的原生并发模型构建,使用 async/await 来处理异步操作。
简化的状态管理:AsyncCore 通过提供内置的异步状态流和高效的操作分发方式,简化了响应式架构。
错误处理和副作用:AsyncCore 包括简化的错误处理和对异步副作用的支持。
线程安全:由于 AsyncCore 构建于 Swift 的 Actor 系统之上,因此它确保了对状态和操作的线程安全访问。
查看示例详情
/// on ViewController with Core
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)
}
...
/// on ViewController with AsyncCore
class ViewController: UIViewController {
private var core: AsyncMainCore?
override func viewDidLoad() {
super.viewDidLoad()
Task {
let core = await AsyncMainCore(initialState: .init())
self.core = core
self.bind(core: core)
}
}
private func bind(core: AsyncMainCore) {
Task {
for await count in core.states.compactMap(\.count) {
print("Count: \(count)")
}
}
Task {
for await count in core.states.count {
print("Count: \(count)")
}
}
}
private func bind() {
Task {
if let counts = self.core?.states.count {
for await count in counts {
print("Count: \(count)")
}
}
}
}
@IBAction func increaseTapped() {
core?.send(.increase)
}
@IBAction func decreaseTapped() {
core?.send(.decrease)
}
}
actor AsyncMainCore: AsyncCore {
var currentState: State
enum Action: Equatable, Hashable {
case increase
case decrease
}
struct State: Equatable, Sendable {
var count = 0
}
nonisolated(unsafe) var currentState: State = .init()
var states: AsyncCoreSequence<State>
var continuation: AsyncStream<State>.Continuation
init(initialState: State) async {
self.currentState = initialState
let (states, continuation) = AsyncStream<State>.makeStream()
self.states = await .init(states)
self.continuation = continuation
}
func reduce(state: State, action: Action) async -> State {
var newState = state
switch action {
case .increase:
newState.count += 1
case .decrease:
newState.count -= 1
}
return newState
}
}
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
}
}
不仅支持简单的核心,也支持复杂的核心。例如,副作用和错误处理。当涉及到这些时,你可以使用 AsyncCore
或 PublisherCore
。
它与 Core 没有太大区别,因为 AnyCore 也符合。
此方法在 AnyCore 中定义,当你处理由副作用生成的 publisher 时,将其发送到该函数中。你也可以在 handleError(error: Error)
函数中处理所有错误
这是 PublisherCore
的一个示例
class MainCore: PublisherCore {
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
}
}
复制这些代码用于 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 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。