KeyPathBox
为添加某些功能而包装 Object。
现在我为异步初始化 Object 和对该对象的引用及修改提供 FutureBox。
FutureBox
FutureBox 受到 Combine 的 Future 的启发。它为 Box 添加了引用和修改初始化对象的特性。
// It will be initialized on current thread
let futureBox = FutureBox<SomeObject, SomeError> { complete in
complete(.success(SomeObject()))
}
futureBox[innerKeyPath: \.self] // Optional(SomeObject)
与 Future 一样,它可以在后台线程上初始化。它可以用来初始化大型对象。
// It will be initialized on background thread
let futureBox = FutureBox<SomeLargeObject, SomeError> { complete in
DispatchQueue.global().async {
complete(.success(SomeLargeObject()))
}
}
// before initialization Completed
futureBox[innerKeyPath: \.self] // nil
// waiting for initialization Complete
//
futureBox.sink { result in
// executed on background thread
switch result {
case .success(let largeOject):
// use object
case .failure(let error):
//user error
}
}
你可以在 Box 中修改对象。修改后下溢将获取修改后的结果。
// modifying
futureBox[innerKeyPath: \.variableProperty] = ...
futureBox.sink { result in // this will get modifed Object Immidiately
switch result {
case .success(let largeOject):
// use object
case .failure(let error):
//user error
}
}
或者你可以使用 map 操作符修改 Box 本身。
let futureBox = FutureBox<SomeObject, SomeError> { complete in
complete(.success(SomeObject()))
}
let anotherFutureBox = futureBox.map { someObject in AnotherObject(someObject) }
futureBox[innerKeyPath: \.self] // Optional(AnotherObject)
你也可以使用 receive 操作符切换事件接收线程。
let futureBox = FutureBox<SomeLargeObject, SomeError> { complete in
DispatchQueue.global().async {
complete(.success(SomeLargeObject()))
}
}
futureBox
.receive(on: .main) // change current thread to main thread
.sink { result in
switch result {
case .success(let largeOject):
// use object
case .failure(let error):
//user error
}
}
需求
- Xcode 10.X 及以上版本
- Swift 4 及以上版本
安装
KeyPathBox 不包含任何外部依赖。
现在我只提供 CocoaPods
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'KeyPathBox'
end
# RxTest and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
pod 'KeyPathBox'
end
替换 YOUR_TARGET_NAME,然后在 Podfile 目录下输入
$ pod install
参考
OpenCombine (为了实现FutureBox,我从这个仓库使用了源代码)