Manos Chorianopoulos

add cache to UrlImages

......@@ -130,24 +130,20 @@ extension CouponView {
}
struct ImageView: View {
@ObservedObject var imageLoader:ImageLoaderGifts
@State var image:UIImage = UIImage()
@ObservedObject var imageLoader:UrlImageModel
var uiscreen = UIScreen.main.bounds
init(withURL url:String) {
imageLoader = ImageLoaderGifts(urlString:url)
imageLoader = UrlImageModel(urlString:url)
}
var body: some View {
Image(uiImage: image)
Image(uiImage: imageLoader.image ?? UIImage())
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: self.uiscreen.width, height: self.uiscreen.height * 0.25)
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
}
}
......
......@@ -179,24 +179,88 @@ struct RoundedCorner: Shape {
}
}
class ImageLoaderGifts: ObservableObject {
var didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
class UrlImageModel: ObservableObject {
@Published var image: UIImage?
var urlString: String?
var imageCache = ImageCache.getImageCache()
func loadImage() {
if loadImageFromCache() {
print("Cache hit")
return
}
print("Cache miss, loading from url")
loadImageFromUrl()
}
init(urlString:String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
self.data = data
}
func loadImageFromCache() -> Bool {
guard let urlString = urlString else {
return false
}
guard let cacheImage = imageCache.get(forKey: urlString) else {
return false
}
image = cacheImage
return true
}
func loadImageFromUrl() {
guard let urlString = urlString else {
return
}
let url = URL(string: urlString)!
let task = URLSession.shared.dataTask(with: url, completionHandler: getImageFromResponse(data:response:error:))
task.resume()
}
func getImageFromResponse(data: Data?, response: URLResponse?, error: Error?) {
guard error == nil else {
print("Error: \(error!)")
return
}
guard let data = data else {
print("No data found")
return
}
DispatchQueue.main.async {
guard let loadedImage = UIImage(data: data) else {
return
}
self.imageCache.set(forKey: self.urlString!, image: loadedImage)
self.image = loadedImage
}
}
init(urlString:String) {
self.urlString = urlString
loadImage()
}
}
class ImageCache {
var cache = NSCache<NSString, UIImage>()
func get(forKey: String) -> UIImage? {
return cache.object(forKey: NSString(string: forKey))
}
func set(forKey: String, image: UIImage) {
cache.setObject(image, forKey: NSString(string: forKey))
}
}
extension ImageCache {
private static var imageCache = ImageCache()
static func getImageCache() -> ImageCache {
return imageCache
}
}
......@@ -286,29 +350,25 @@ extension GiftsView {
}
struct ImageView: View {
@ObservedObject var imageLoader:ImageLoaderGifts
@State var image:UIImage = UIImage()
@ObservedObject var imageLoader:UrlImageModel
@State var width:CGFloat
@State var isFill:Bool
var uiscreen = UIScreen.main.bounds
init(withURL url:String , width:CGFloat, isFill:Bool) {
imageLoader = ImageLoaderGifts(urlString:url)
imageLoader = UrlImageModel(urlString:url)
self.width = width
self.isFill = isFill
}
var body: some View {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: isFill ? .fill : .fit)
.frame(width: self.width)
.frame(maxHeight: .infinity)
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
Image(uiImage: imageLoader.image ?? UIImage())
.resizable()
.aspectRatio(contentMode: isFill ? .fill : .fit)
.frame(width: self.width)
.frame(maxHeight: .infinity)
}
}
......