Wrapper of Object for adding Some Capability.
Now I provide FutureBox for Asynchronous Initialization of Object and Reference & Modification of that Object.
FutureBox is inspired by Combine's Future. It adds feature to refer and modify initialized object itself in Box.
// It will be initialized on current thread
let futureBox = FutureBox<SomeObject, SomeError> { complete in
complete(.success(SomeObject()))
}
futureBox[innerKeyPath: \.self] // Optional(SomeObject)
As Future does, It could be initlaized on background thread. It can be used to initialize large-scale object.
// 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
}
}
you can modify object in the box. Sinking afer modification will get modified result
// 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
}
}
or you can change box itself using map operator
let futureBox = FutureBox<SomeObject, SomeError> { complete in
complete(.success(SomeObject()))
}
let anotherFutureBox = futureBox.map { someObject in AnotherObject(someObject) }
futureBox[innerKeyPath: \.self] // Optional(AnotherObject)
you also switch event receiving thread with receive operator
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 and later
- Swift 4 and later
KeyPathBox doesn't contain any external dependencies.
Now I provide CocoaPods Only
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'KeyPathBox'
end
Replace YOUR_TARGET_NAME and then, in the Podfile directory, type:
$ pod install
OpenCombine(For FutureBox Implementation, I used source code from this repository)