babylonhealth / Bento

Swift library for building component-based interfaces on top of UITableView and UICollectionView 🍱
MIT License
374 stars 11 forks source link

[CNSMR-1590] New `willMount` and `willUnmount` hooks to support atomic component DSLs. #162

Closed andersio closed 5 years ago

andersio commented 5 years ago

https://babylonpartners.atlassian.net/browse/CNSMR-1590

Two new hooks so we won't need to create wrapping views for certain classes of additive behaviours, and won't need to rely on ObjC associated objects.

Examples

Styling

The branch includes a pilot which applies a StyleSheet to the view using didMount and reverts it in willUnmount.

let styleSheet = StyleSheet()
    .setting(\.backgroundColor, .blue)

let styledComponent: AnyRenderable = component.styling(styleSheet)

Constraint decorators

e.g. The height(_:) and width(_:) DSL operators can now be implemented as:

private let heightConstraintKey = ViewStorage.Key<NSLayoutConstraint>()

struct HeightDecorator<R: Renderable>: Renderable {
    let base: R
    let height: CGFloat

    // init decl...

    func render(in view: R.View) {
        base.render(in: view)
    }

    func didMount(to view: View, storage: ViewStorage) {
        base.didMount(to: view, storage: storage)
        storage[heightConstraintKey] = view.heightAnchor
            .constraint(equalToConstant: height)
            .activated()
    }

    func willUnmount(from view: View, storage: ViewStorage) {
        base.willUnmount(from: view, storage: storage)
        storage[heightConstraintKey]?.isActive = false
    }
}