carson-katri / swift-request

Declarative HTTP networking, designed for SwiftUI
MIT License
727 stars 41 forks source link

`@Requested` property wrapper and reimplementation of `RequestView` #46

Closed carson-katri closed 3 years ago

carson-katri commented 3 years ago

@Requested

This allows a Request to be specified in a property wrapper, and it will automatically update your View's body when the Request finishes. The projectedValue contains the status of the Request as a RequestStatus enum:

struct TodoList: View {
  @Requested private var allTodos = AnyRequest<[Todo]> {
    Url("https://jsonplaceholder.typicode.com/todos")
  }

  var body: some View {
    switch $allTodos {
    case .loading: ProgressView()
    case let .failure(error): Text(error.localizedDescription)
    case let .success(todos):
      List(todos) { todo in
        Label(todo.title, systemImage: "checkmark.circle\(todo.completed ? ".fill" : "")")
      }
    }
  }
}

RequestView

It was re-implemented to fix refreshing the result (available on iOS 14+, macOS 11+, etc. due to a requirement of the onChange modifier). It also now has an initializer that uses the RequestStatus enum in it's body. This is equivalent to the property wrapper example above:

RequestView(AnyRequest<[Todo]> {
  Url("https://jsonplaceholder.typicode.com/todos")
}) { result in
  switch result {
  case .loading: ProgressView()
  case let .failure(error): Text(error.localizedDescription)
  case let .success(todos):
    List(todos) { todo in
      Label(todo.title, systemImage: "checkmark.circle\(todo.completed ? ".fill" : "")")
    }
  }
}

The old initializers, with Optional results in their body and a requirement of a TupleView have been deprecated, but are still supported.

Resolves #45