Skip to content

Smart Key Paths and Bindings #331

@andersio

Description

@andersio

With the accepted the Smart Key Paths for Swift 4, BindingTarget would be supercharged with the ability to access any properties and their subfields of objects and mutable properties without hand-written closures.

It could remove the needs of all binding targets in the reactive extensions. That said it depends on how it would be incorporate in our binding syntaxes.

  1. The most verbose approach would be:

    BindingTarget(object: control, for: \.isEnabled) <~ viewModel.isEnabled
    BindingTarget(object: view, for: \.label.text) <~ viewModel.title
  2. The verbose approach to reuse reactive would be:

    control.reactive.bindingTarget(\.isEnabled) <~ viewModel.isEnabled
    control.reactive.bindingTarget(\.label.text) <~ viewModel.title
  3. The old-ObjC macro-ish approach would be:

    r(control, \.isEnabled) <~ viewModel.isEnabled
    r(view, \.label.text) <~ viewModel.title

    (3) is a serious contender given its brevity as compared to (1). It can also replace .reactive as the gateway to the reactive extensions. It also does not suffer as much as .reactive from cross-module name conflicts, since at least it can still be disambiguated by the module name.

    The downside is that it violates the Swift API Guidelines, which state that free functions should be used only:

    1. When there’s no obvious self
    2. When the function is an unconstrained generic
    3. When function syntax is part of the established domain notation
  4. The approach to reuse reactive would be:

    // A `for:` label doesn't seem necessary here.
    control.reactive(\.isEnabled) <~ viewModel.isEnabled
    control.reactive(\.label.text) <~ viewModel.title
  5. An infix operator based approach would be:

    control .~ \.isEnabled <~ viewModel.isEnabled
    control .~ \.label.text <~ viewModel.title
  6. A prefix or postfix operator based approach would be:

    // The operator returns `(KeyPath<Base, U>) -> BindingTarget<U>`.
    .~control(\.isEnabled) <~ viewModel.isEnabled
    .~control(\.label.text) <~ viewModel.title

There are more combinations, but these are listed based on the requirement of having enough contextual information for autocompletion of key paths to show up in the LTR order.

I suppose most would prefer (4) or (5).

/cc @ReactiveCocoa/reactiveswift

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions