Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Last active September 15, 2022 19:02
Show Gist options
  • Star 58 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save chriseidhof/2c3bcdfa5bfa0795b33bd17f1e88771d to your computer and use it in GitHub Desktop.
Save chriseidhof/2c3bcdfa5bfa0795b33bd17f1e88771d to your computer and use it in GitHub Desktop.
final class Loader: BindableObject {
let didChange = PassthroughSubject<Data?, Never>()
var task: URLSessionDataTask!
var data: Data? = nil {
didSet {
didChange.send(data)
}
}
init(_ url: URL) {
task = URLSession.shared.dataTask(with: url, completionHandler: { data, _, _ in
DispatchQueue.main.async {
self.data = data
}
})
task.resume()
}
deinit {
task.cancel()
}
}
let placeholder = UIImage(named: "placeholder.jpg")!
struct MyView: View {
init(url: URL) {
self.imageLoader = Loader(url)
}
@ObjectBinding private var imageLoader: Loader
var image: UIImage? {
imageLoader.data.flatMap(UIImage.init)
}
var body: some View {
Image(uiImage: image ?? placeholder)
}
}
@Plnda
Copy link

Plnda commented Jun 6, 2019

How would you go and make this change animate in ?

@loganmoseley
Copy link

I haven't gotten to try SwiftUI myself, but I think I remember an example from a session to animate a change:

    var body: some View {
        withAnimation { Image(uiImage: image ?? placeholder) }
    }

@JaroVoltix
Copy link

That code make Xcode unable to build my project or Segmentation fault occurs

@tagmetag
Copy link

tagmetag commented Nov 2, 2019

Update code for newest (when @BindableObject has been depreciated):

import SwiftUI

final class Loader: ObservableObject {
    
    var task: URLSessionDataTask!
    @Published var data: Data? = nil
    
    init(_ url: URL) {
        task = URLSession.shared.dataTask(with: url, completionHandler: { data, _, _ in
            DispatchQueue.main.async {
                self.data = data
            }
        })
        task.resume()
    }
    deinit {
        task.cancel()
    }
}

let placeholder = UIImage(named: "placeholder.jpg")!

struct AsyncImage: View {
    init(url: URL) {
        self.imageLoader = Loader(url)
    }
    
    @ObservedObject private var imageLoader: Loader
    var image: UIImage? {
        imageLoader.data.flatMap(UIImage.init)
    }
    
    
    var body: some View {
        Image(uiImage: image ?? placeholder)
    }
}

@Hakonslie
Copy link

Thanks man this was really useful :)

@swagatnayak
Copy link

Thanks, dear....really you save my day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment