Skip to content

Commit

Permalink
Merge branch 'release/0.6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
antonio-war committed Sep 19, 2024
2 parents 0b89b78 + 4ec6a06 commit 923e0c0
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 42 deletions.
43 changes: 36 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,45 @@ The `Request` property wrapper allows you to make a network request and decode t
It is inspired by SwiftData's @Query to provide the user with a familiar interface.

```swift
@Request(url: "https://jsonplaceholder.typicode.com/posts")
var posts: [Post]?

@Request(url: "https://jsonplaceholder.typicode.com/posts/1")
var post: Post?
@Request(
client: SwiftyNetworkingClient(),
url: URL(string: "https://jsonplaceholder.typicode.com/posts"),
method: .get,
headers: ["Content-Type": "application/json"],
cachePolicy: .returnCacheDataElseLoad,
timeout: 10,
decoder: JSONDecoder()
)
var response: Response<[Post]>
```

The request is executed automatically as soon as the view is created, so you can directly access your object inside the body.
If there is an error, the object will be nil.
Each request is associated with a Response object which is trivially a three-state enum (loading, success and failure).

The request is executed automatically as soon as the view is created, so you can directly access to the response inside the view body and show a different aspect of the view for each state through a simple switch.

```swift
List {
switch response {
case .loading:
LoadingCell()
case .success(let posts):
ForEach(posts, id: \.id) { post in
PostCell(post)
}
case .failure(let error):
ErrorCell(error)
}
}
```
In case your request failed or you just want to update the result you can use its projectedValue to call the refresh method that will cause the view to be redrawn and the result to be updated.

```swift
Button("Refresh") {
Task {
await $response.refresh()
}
}
```
---
# Support
Your generous donations help sustain and improve this project. Here's why supporting us is important:
Expand Down
14 changes: 14 additions & 0 deletions Sources/SwiftyNetworking/Enums/Response.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Response.swift
// SwiftyNetworking
//
// Created by Antonio Guerra on 19/09/24.
//

import Foundation

public enum Response<Model: Decodable> {
case loading
case success(Model)
case failure(Error)
}
32 changes: 21 additions & 11 deletions Sources/SwiftyNetworking/PropertyWrappers/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import Foundation
import SwiftUI

@propertyWrapper
public struct Request<Model: Decodable>: DynamicProperty {
public struct Request<Model: Decodable>: DynamicProperty, Refreshable {
public typealias Method = SwiftyNetworkingRequest.Method
@State private var model: Model? = nil
@State private var error: Error? = nil
@State private var response: Response<Model> = .loading
@State private var fetching: Bool = false

let client: SwiftyNetworkingClient
Expand Down Expand Up @@ -69,17 +68,25 @@ public struct Request<Model: Decodable>: DynamicProperty {
)
}

public var wrappedValue: Model? {
model
public var wrappedValue: Response<Model> {
response
}


public var projectedValue: Refreshable {
self
}

private var shouldUpdate: Bool {
model == nil && error == nil && fetching == false
switch response {
case .loading: !fetching
default: false
}
}

@MainActor
func fetch() async {
do {
self.response = .loading
self.fetching = true
let request = try SwiftyNetworkingRequest(
url: url,
Expand All @@ -89,10 +96,11 @@ public struct Request<Model: Decodable>: DynamicProperty {
cachePolicy: cachePolicy,
timeout: timeout
)
self.model = try await client.send(request, decoding: Model.self, using: decoder)
let model = try await client.send(request, decoding: Model.self, using: decoder)
self.response = .success(model)
self.fetching = false
} catch {
self.error = error
self.response = .failure(error)
self.fetching = false
}
}
Expand All @@ -103,9 +111,11 @@ public struct Request<Model: Decodable>: DynamicProperty {
}

Task {
self.model = nil
self.error = nil
await fetch()
}
}

public func refresh() async {
await fetch()
}
}
10 changes: 10 additions & 0 deletions Sources/SwiftyNetworking/Protocols/Refreshable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// Refreshable.swift
// SwiftyNetworking
//
// Created by Antonio Guerra on 19/09/24.
//

public protocol Refreshable {
func refresh() async
}
24 changes: 0 additions & 24 deletions Tests/SwiftyNetworkingTests/PropertyWrappers/RequestTests.swift

This file was deleted.

0 comments on commit 923e0c0

Please sign in to comment.