Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] @ResourceBacked property wrapper #307

Open
wants to merge 28 commits into
base: file-cache
Choose a base branch
from

Conversation

pcantrell
Copy link
Member

@pcantrell pcantrell commented Apr 8, 2020

A common idiom in Siesta projects is to have UI code point at some resource that can change, and whenever it changes, to:

  • stop observing the old resource,
  • add one or more observers to the new resource (the same observers every time), and
  • load if needed.

The Siesta docs and the example project recommend doing this via didSet:

var doodadsResource: Resource? {
    didSet {
        oldValue?.removeObservers(ownedBy: self)

        doodadsResource?
            .addObserver(self)
            .addObserver(statusOverlay, owner: self)
            .loadIfNeeded()
    }
}

var doodads: [Doodad] {  // convenience accessor
    return doodadsResource?.typedContent() ?? []
}

Swift 5.2’s property wrappers give us a better option. This PR adds a @ResourceBacked property wrapper that lets any variable take its value from a Siesta resource.

The example above becomes:

@ResourceBacked(default: [])
var doodads: [Doodad]
// during initialization, e.g. in viewDidLoad() or some such:
$doodads.addObserver(self)
$doodads.addObserver(statusOverlay)

The doodads variable now behaves as if it is a read-only Doodad array; for example, we can do this:

for doodad in doodads {  // just works
    print(doodad.name)
}

However, that array comes from a Siesta resource — and we can switch which resource on the fly:

$doodads.resource = api.resource(“foo”).child(newDoodadID)

Changing the resource in this way automatically:

  • removes our little flock of observers from the old resource (if any),
  • adds our flock of observers to the new resource (if any),
  • sends the appropriate events to the observers so they show the change immediately, and
  • triggers a call to loadIfNeeded().

Future work on this feature

  • The wrapper should detect whether the resource’s value does not match the variable’s type, and report this as an error via $doodads.error. This would give better error reporting to the user if the server returns well-formed but unexpected content. (If you ask for $doodads.resource?.latestError, you still get only underlying resource errors, since resources (at least in Siesta 1.0) have freely typed content.)
  • Property wrapper should wrap response to observers to reflect the above
  • Clients should be able to opt out of automatic loadIfNeeded
  • Any facilities necessary for doing custom requests?
  • Make sure it plays nice with SwiftUI

@pcantrell pcantrell added this to To do in 1.6 Apr 8, 2020
@pcantrell pcantrell moved this from To do to In progress in 1.6 Apr 8, 2020
@pcantrell pcantrell changed the title @ResourceBacked property wrapper [WIP] @ResourceBacked property wrapper Apr 10, 2020
@pcantrell pcantrell force-pushed the file-cache branch 3 times, most recently from 2751763 to 63baa8e Compare October 24, 2021 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
1.6
  
In progress
Development

Successfully merging this pull request may close these issues.

None yet

1 participant