Skip to content

Commit

Permalink
v0.4 Firebase and StateObject Support
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam-Spencer committed Mar 4, 2021
1 parent 3b68b12 commit 875cf2b
Show file tree
Hide file tree
Showing 5 changed files with 355 additions and 129 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# FetchImage 0.x

## FetchImage 0.4.0

*Mar 03, 2021*

- **Internal Change** `ImageRequest` objects are now optional and may not be immediately fulfilled when initializing a `FetchImage` instance. This allows expansion of the API for additional changes and improvements.
- Google Firebase support. Using the new convenience initializer to create a `FetchImage` instance with a Firestore `StorageReference` instead of directly from a URL. Optionally, supply any cached URL content when using this initializer to decrease Firestore roundtrips.
- Fixed and expanded in-line documentation.

## FetchImage 0.3.0

*Dec 26, 2020*

- **Breaking Change** `FetchImage` no longer starts the request in the initializer, you must call `fetch()`.
- Add `reset()` method which clears the entire `FetchImage` state including the downloaded image. This is crucial for long lists where you don't want `FetchImage` instances to retains images which are off screen.
- Add `reset()` method which clears the entire `FetchImage` state including the downloaded image. This is crucial for long lists where you don't want `FetchImage` instances to retain images which are off screen.

## FetchImage 0.2.1

Expand Down
103 changes: 101 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,13 +1,112 @@
{
"object": {
"pins": [
{
"package": "abseil",
"repositoryURL": "https://github.com/firebase/abseil-cpp-SwiftPM.git",
"state": {
"branch": null,
"revision": "05d8107f2971a37e6c77245b7c4c6b0a7e97bc99",
"version": "0.20200225.0"
}
},
{
"package": "BoringSSL-GRPC",
"repositoryURL": "https://github.com/firebase/boringssl-SwiftPM.git",
"state": {
"branch": null,
"revision": "7bcafa2660bc58715c39637494550d1ed7cd7229",
"version": "0.0.7"
}
},
{
"package": "Firebase",
"repositoryURL": "https://github.com/firebase/firebase-ios-sdk.git",
"state": {
"branch": null,
"revision": "14dff7e19375288c7e34df8444c85d314f26d7cf",
"version": "7.6.0"
}
},
{
"package": "GoogleAppMeasurement",
"repositoryURL": "https://github.com/google/GoogleAppMeasurement.git",
"state": {
"branch": null,
"revision": "38205d8e39f806f71b048f93427337c9511c9402",
"version": "7.5.1"
}
},
{
"package": "GoogleDataTransport",
"repositoryURL": "https://github.com/google/GoogleDataTransport.git",
"state": {
"branch": null,
"revision": "2e8a342494d20fcf209b61a45cddc1668b5ccc6d",
"version": "8.2.0"
}
},
{
"package": "GoogleUtilities",
"repositoryURL": "https://github.com/google/GoogleUtilities.git",
"state": {
"branch": null,
"revision": "2c7d33099a3c3da1139bb1e8eb94e46e0dacf075",
"version": "7.2.2"
}
},
{
"package": "gRPC",
"repositoryURL": "https://github.com/firebase/grpc-SwiftPM.git",
"state": {
"branch": null,
"revision": "91b62619e6c83bc5f1b99d9d60fe46b2862d3a5a",
"version": "1.28.2"
}
},
{
"package": "GTMSessionFetcher",
"repositoryURL": "https://github.com/google/gtm-session-fetcher.git",
"state": {
"branch": null,
"revision": "91ed3d188eb95705fef3c249453b81f32dc557d1",
"version": "1.5.0"
}
},
{
"package": "leveldb",
"repositoryURL": "https://github.com/firebase/leveldb.git",
"state": {
"branch": null,
"revision": "fa1f25f296a766e5a789c4dacd4798dea798b2c2",
"version": "1.22.1"
}
},
{
"package": "nanopb",
"repositoryURL": "https://github.com/firebase/nanopb.git",
"state": {
"branch": null,
"revision": "c2d43e59d8ec880ed261366818f0cacc5c8cc2e6",
"version": "2.30907.0"
}
},
{
"package": "Nuke",
"repositoryURL": "https://github.com/kean/Nuke.git",
"state": {
"branch": null,
"revision": "e901272a7cc5a28734d4f196d543edcf7efd8f4c",
"version": "9.0.0"
"revision": "961597d324949c7003c77d602bfc4d5519b47e81",
"version": "9.2.4"
}
},
{
"package": "Promises",
"repositoryURL": "https://github.com/google/promises.git",
"state": {
"branch": null,
"revision": "afa9a1ace74e116848d4f743599ab83e584ff8cb",
"version": "1.2.12"
}
}
]
Expand Down
12 changes: 9 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.1
// swift-tools-version:5.3

import PackageDescription

Expand All @@ -14,9 +14,15 @@ let package = Package(
.library(name: "FetchImage", targets: ["FetchImage"])
],
dependencies: [
.package(url: "https://github.com/kean/Nuke.git", from: "9.0.0")
.package(url: "https://github.com/kean/Nuke.git", from: "9.2.0"),
.package(name: "Firebase", url: "https://github.com/firebase/firebase-ios-sdk.git", from: "7.3.0")
],
targets: [
.target(name: "FetchImage", dependencies: ["Nuke"], path: "Source")
.target(name: "FetchImage",
dependencies: [
"Nuke",
.product(name: "FirebaseStorage", package: "Firebase")
],
path: "Source")
]
)
110 changes: 60 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,69 @@

# FetchImage

`FetchImage` is a Swift package that makes it easy to download images using [`Nuke`](https://github.com/kean/Nuke) and display them in SwiftUI apps
`FetchImage` is a Swift package that makes it easy to download images using [`Nuke`](https://github.com/kean/Nuke) and display them in SwiftUI apps. This particular fork comes bundled with support for [Google Firebase](https://github.com/firebase/firebase-ios-sdk) `StorageReferences`.

> **Note**. This is an API preview. It is not battle-tested yet, and might change in the future.
## Usage

Here is an example of using `FetchImage` in a custom SwiftUI view.

```swift
public struct ImageView: View {
@ObservedObject var image: FetchImage

public var body: some View {
ZStack {
Rectangle().fill(Color.gray)
image.view?
.resizable()
.aspectRatio(contentMode: .fill)
}

// Cancel and restart the request during scrolling
// If the view is still on screen, use `cancel()` instead of `reset()`.
.onAppear(perform: image.fetch)
.onDisappear(perform: image.reset)

// (Optional) Animate image appearance
.animation(.default)
}
}

struct ImageView_Previews: PreviewProvider {
static var previews: some View {
let url = URL(string: "https://cloud.githubusercontent.com/assets/1567433/9781817/ecb16e82-57a0-11e5-9b43-6b4f52659997.jpg")!
return ImageView(image: FetchImage(url: url))
.frame(width: 80, height: 80)
.clipped()
}
}
```

`FetchImage` gives you full control over how to manage the download and how to display the image. For example, one thing that you could do is to replace `onAppear` and `onDisappear` hooks to lower the priority of the requests instead of cancelling them. This might be useful if you want to continue loading and caching the images even if the user leaves the screen, but you still want the images the are currently on screen to be downloaded first.

```swift
.onAppear {
self.image.priority = .normal
self.image.fetch() // Restart the request if previous download failed
}
.onDisappear {
self.image.priority = .low
}
```

You may also initialize a `FetchImage` using a Firestore `StorageReference`. These references can be easily created synchronously, but require an asynchronous call in order generate URLs for fetching the requested content. Unfortunately, this makes image loading in SwiftUI rather difficult. Using `Nuke` and `Firebase` together simplifies the whole process quite a bit:

```swift
@State referencedImage: StorageReference

public var body: some View {
ImageView(image: FetchImage(regularStorageRef: referencedImage)
.animation(.default)
}
```

## Overview

`FetchImage` is an observable object (`ObservableObject`) that allows you to manage the download of a single image and observe the results of the download. All of the changes to the download state are published using properties marked with `@Published` property wrapper.
Expand Down Expand Up @@ -81,54 +140,6 @@ FetchImage(regularUrl: highQualityUrl, lowDataUrl: lowQualityUrl)

`FetchedImage.init(regularUrl:lowDataUrl:pipeline:)` is a convenience initializer that fetches the image with a regular URL with constrained network access disabled, and if the download fails because of the constrained network access, uses a low data URL instead. It also handles the scenarios like fetching a high quality image when unconstrained network access is restored.

## Usage

Here is an example of using `FetchImage` in a custom SwiftUI view.

```swift
public struct ImageView: View {
@ObservedObject var image: FetchImage

public var body: some View {
ZStack {
Rectangle().fill(Color.gray)
image.view?
.resizable()
.aspectRatio(contentMode: .fill)
}

// Cancel and restart the request during scrolling
// If the view is still on screen, use `cancel()` instead of `reset()`.
.onAppear(perform: image.fetch)
.onDisappear(perform: image.reset)

// (Optional) Animate image appearance
.animation(.default)
}
}

struct ImageView_Previews: PreviewProvider {
static var previews: some View {
let url = URL(string: "https://cloud.githubusercontent.com/assets/1567433/9781817/ecb16e82-57a0-11e5-9b43-6b4f52659997.jpg")!
return ImageView(image: FetchImage(url: url))
.frame(width: 80, height: 80)
.clipped()
}
}
```

`FetchImage` gives you full control over how to manage the download and how to display the image. For example, one thing that you could do is to replace `onAppear` and `onDisappear` hooks to lower the priority of the requests instead of cancelling them. This might be useful if you want to continue loading and caching the images even if the user leaves the screen, but you still want the images the are currently on screen to be downloaded first.

```swift
.onAppear {
self.image.priority = .normal
self.image.fetch() // Restart the request if previous download failed
}
.onDisappear {
self.image.priority = .low
}
```

# Requirements

| Nuke | Swift | Xcode | Platforms |
Expand All @@ -138,4 +149,3 @@ struct ImageView_Previews: PreviewProvider {
# License

FetchImage is available under the MIT license. See the LICENSE file for more info.

Loading

0 comments on commit 875cf2b

Please sign in to comment.