Display the image in the widgets, and tap the image to see ** View ** and ** ViewModel ** used for linking the app with the URL scheme.
Does try? Data (contentsOf: URL) caches https://stackoverflow.com/a/57826757
URLImageViewModel.swift
import SwiftUI
final class URLImageViewModel: ObservableObject {
@Published var downloadData: Data? = nil
let url: String
init(url: String, isSync: Bool = false) {
self.url = url
if isSync {
self.downloadImageSync(url: self.url)
} else {
self.downloadImageAsync(url: self.url)
}
}
func downloadImageAsync(url: String) {
guard let imageURL = URL(string: url) else {
return
}
let cache = URLCache.shared
let request = URLRequest(url: URL(string: url)!, cachePolicy: URLRequest.CachePolicy.returnCacheDataElseLoad)
if let data = cache.cachedResponse(for: request)?.data {
self.downloadData = data
}else {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
DispatchQueue.main.async {
self.downloadData = data
}
}
}
}
func downloadImageSync(url: String) {
guard let imageURL = URL(string: url) else {
return
}
let cache = URLCache.shared
let request = URLRequest(url: URL(string: url)!, cachePolicy: URLRequest.CachePolicy.returnCacheDataElseLoad)
if let data = cache.cachedResponse(for: request)?.data {
self.downloadData = data
}else {
let data = try? Data(contentsOf: imageURL)
self.downloadData = data
}
}
}
URLImageView.swift
import SwiftUI
struct URLImageView: View {
@ObservedObject var viewModel: URLImageViewModel
var body: some View {
if let imageData = self.viewModel.downloadData {
if let image = UIImage(data: imageData) {
return Image(uiImage: image).resizable().scaledToFit()
} else {
return Image(uiImage: UIImage()).resizable().scaledToFit()
}
} else {
return Image(uiImage: UIImage()).resizable().scaledToFit()
}
}
}
LinkURLImageView.swift
import SwiftUI
struct LinkURLImageView: View {
let url: URL
let imageUrlString: String
let isSyncURLImage: Bool
init(url: URL, imageUrlString: String, isSyncURLImage: Bool = false) {
self.url = url
self.imageUrlString = imageUrlString
self.isSyncURLImage = isSyncURLImage
}
var body: some View {
Link(destination: url) {
let imageViewModel = URLImageViewModel(url: imageUrlString, isSync: isSyncURLImage)
URLImageView(viewModel: imageViewModel)
}
}
}
Asynchronous is not available for widgets, so use synchronous communication. (For asynchronous, specify false for isSyncURLImage)
WidgetEntryView.swift
import SwiftUI
struct WidgetEntryView: View {
var body: some View {
LinkURLImageView(url: URL(string: "URL of the link you tapped (widgets)://)")!,
imageUrlString: "Image URL",
isSyncURLImage: true)
}
}