-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Adam Share edited this page Oct 2, 2020
·
12 revisions
LifecycleKit is a framework for building lifecycle-aware architecture components.
Inspired by RIBs and Android Jetpack Lifecycle. Complemented by Needle, a compile-time safe Swift dependency injection framework.
LifecycleKit provides protocols and implementations that can be used to facilitate building safe and scalable application architecture.
initialized |
Lifecycle has been initialized but not yet active. |
active |
Lifecycle is currently active. |
inactive |
Lifecycle is currently inactive. |
deinitialized |
Lifecycle deinit called. |
Todo: description
Conforming Types
LifecycleOwner
LifecycleDependent
ScopeLifecycle
ViewLifecycle
Todo: description
Todo: description
class MyLifecycleOwner: LifecycleOwner {
let scopeLifecycle: ScopeLifecycle = ScopeLifecycle()
}
Todo: description
class MyLifecycleSubscriber: LifecycleSubscriber {
init(scopeLifecycle: ScopeLifecycle) {
subscribe(to: scopeLifecycle)
}
func didLoad(_ lifecyclePublisher: LifecyclePublisher) {
// First active
}
func didBecomeActive(_ lifecyclePublisher: LifecyclePublisher) {
// On active
}
func didBecomeInactive(_ lifecyclePublisher: LifecyclePublisher) {
// On inactive
}
}
Todo: description
class MyParentLifecycleOwner: LifecycleOwner, LifecycleOwnerRouting {
let scopeLifecycle: ScopeLifecycle = ScopeLifecycle()
let childLifecycleOwner: LifecycleOwner
init(childLifecycleOwner: LifecycleOwner) {
self.childLifecycleOwner = childLifecycleOwner
}
func makeChildActive() {
if attachChild(childLifecycleOwner) {
print("Child is now active")
}
}
func makeChildInactive() {
detachChild(childLifecycleOwner)
}
}
Todo: description
class MyLifecycleDependent: LifecycleDependent {
weak var scopeLifecycle: ScopeLifecycle?
}
Todo: description
class MyParentLifecycleDependent: LifecycleDependent, LifecycleOwnerRouting {
weak var scopeLifecycle: ScopeLifecycle?
let childLifecycleOwner: LifecycleOwner
init(scopeLifecycle: ScopeLifecycle,
childLifecycleOwner: LifecycleOwner) {
self.scopeLifecycle = scopeLifecycle
self.childLifecycleOwner = childLifecycleOwner
}
func makeChildActive() {
if attachChild(childLifecycleOwner) {
print("Child is now active")
}
}
func makeChildInactive() {
detachChild(childLifecycleOwner)
}
}
Todo: description
class AutoCancelLifecycleSubscriber: MyLifecycleSubscriber {
private let textStream: RelayPublisher<String>
init(scopeLifecycle: ScopeLifecycle,
textStream: RelayPublisher<String>) {
self.textStream = textStream
super.init(scopeLifecycle: scopeLifecycle)
}
override func didBecomeActive(_ lifecyclePublisher: LifecyclePublisher) {
super.didBecomeActive(lifecyclePublisher)
textStream
.autoCancel(lifecyclePublisher)
.sink { value in
print("""
Safely capturing \(self) as retain cycle is broken when
\(lifecyclePublisher) becomes inactive deataching from parent scope.
""")
}
}
}
Todo: description
Todo: description
import SwiftUI
class MyViewLifecycleOwner: ViewLifecycleOwner {
let viewLifecycle: ViewLifecycle = ViewLifecycle()
var view: some View {
tracked {
Text("Hello World")
}
}
}
Todo: description
class MyViewLifecycleSubscriber: ViewLifecycleSubscriber {
init(viewLifecycle: ViewLifecycle) {
subscribe(to: viewLifecycle)
}
func viewDidLoad() {
// View initialized
}
func viewDidAppear() {
// On appear
}
func viewDidDisappear() {
// On disappear
}
}
Todo: description
import Lifecycle
import SwiftUI
class LifecycleViewController: LifecycleOwner,
LifecycleSubscriber,
LifecycleOwnerRouting,
ViewLifecycleOwner,
ViewLifecycleSubscriber {
var view: some View {
tracked {
Text("Hello World")
}
}
let scopeLifecycle: ScopeLifecycle = ScopeLifecycle()
let viewLifecycle: ViewLifecycle = ViewLifecycle()
init() {
subscribe(to: scopeLifecycle)
subscribe(to: viewLifecycle)
}
func didLoad(_ lifecyclePublisher: LifecyclePublisher) {}
func didBecomeActive(_ lifecyclePublisher: LifecyclePublisher) {}
func didBecomeInactive(_ lifecyclePublisher: LifecyclePublisher) {}
func viewDidLoad() {}
func viewDidAppear() {}
func viewDidDisappear() {}
}
Todo: description
class SceneDelegate: UIResponder, UIWindowSceneDelegate, RootLifecycle {
let root: LifecycleViewController = LifecycleViewController()
var rootLifecycleOwner: LifecycleOwner {
return root
}
var window: UIWindow?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: root.view)
window.makeKeyAndVisible()
activateRoot()
self.window = window
}
}
App architecture utilizing Lifecycle
to create a scoped business logic tree independent of the view hierarchy.
Presenter |
ViewLifecycleOwner that provides a View to the parent scope and can be referenced as an ObservableObject by the returned view. |
Interactor |
LifecycleOwner that contains business logic and optionally a strong reference to a Router and Presenter. |
Router |
LifecycleDependent that encapsulates and generalizes routing logic between scopes. |
-
Router
is optional because theScopeLifecycle
is owned by theInteractor
which manages both lifecycle state and attaching child scopes. -
Router
does not have a circular reference toInteractor
and instead instaniates with the sharedScopeLifecycle
instance. -
Worker
is no longer needed since anInteractor
can encapsulate business logic as a child of anotherInteractor
. -
Builder
classes are provided as a convenience for type erasure without requiring subclassing.