SDWebImage change cacheMaxCacheAge - ios

How I can change a static value cacheMaxCacheAge when I use SDWebImage? What way is good? I need to cache images for 5 minutes.

In SDWebImage 5.0+ maxCacheAge renamed to maxDiskAge. You can set maximum caching time in seconds like this.
Objetive-c
[SDImageCache sharedImageCache].config.maxDiskAge = 60 * 5; //5 minutes
Swift 4+
SDImageCache.shared.config.maxDiskAge = 60 * 5 //5 minutes
Reference link: https://github.com/SDWebImage/SDWebImage/wiki/5.0-Migration-guide

SDWebImage is providing maxCacheAge property to set the maximum caching time in seconds. We can use shared instance method to access this property.
[SDImageCache sharedImageCache].config.maxCacheAge = 60 * 5; //5 minutes

SWIFT 5+ , SDWebImage 5.13 +, tvOS15+ and maybe other platforms
I found out that simply setting new maxDiskAge property on tvOS 15+ is not enough when storing image with SDImageCache.shared.store , but you indeed need to manually delete the old cache with deleteOldFiles() function. It happens in my case, even though the performing of old cache deletion is allegedly done by library itself after terminating the app as specified in following SO post. This might be only the case for tvOS, but I am not entirely sure if the problem persists also on another platforms. Here is the solution that worked for me:
Deleting expired cache:
SDImageCache.shared.deleteOldFiles()
Setting max cache disk time in seconds:
SDImageCache.shared.config.maxDiskAge = 100000
Storing images to disk:
SDImageCache.shared.store(image, forKey: key, toDisk: true)

Related

URLSessionDownloadDelegate progress not updating

I'm quite new to the topic of IOS development, so it's may a stupid question, but I'm unable to calculate and print the progress of a download task using URLSessionDownloadDelegate.
I was following this guide: https://medium.com/swlh/tracking-download-progress-with-urlsessiondownloaddelegate-5174147009f and its source code from https://github.com/ShawonAshraf/URLSessionProgressTrackerExample but the progress label just jumps from 0 to 100% even with bigger files, which require a few minutes to download.
If it's possible to do so, I would like not to use a third party lib.
I'm using swift 5 with Xcode 11.4 on an iOS 13.4 simulator.
The sample project you've linked performs integer division to calculate the progress, and therefore only ever gives you 0 or 1 as the result.
Replace this line
let percentDownloaded = totalBytesWritten / totalBytesExpectedToWrite
with this
let percentDownloaded = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)

How to cache images only in disk using Kingfisher?

I am using Kingfisher library for downloading and caching images. I am facing some issues in the implementation:
Are the images cached in both memory and disk?
Is there any provision to cache images only on disk?
I have already read multiple posts regarding this, but couldn't find any solution.
Yes, Kingfisher caches images both in memory and on disk.
By default, the amount of RAM that will be used is not even limited, you have to set the value yourself:
ImageCache.default.maxMemoryCost = 1024 * 1024 * yourValue
where 1024 * 1024 * yourValue is the global cost in megapixels (I know this is weird, but it's not megabytes, it's megapixels, because images can have different bit depth, etc).
For example, in my tests, the maximum RAM used with a value of 1024 * 1024 * 500 fluctuates between 120MB and 300MB.
Incidentally, this is also how you tell Kingfisher to never use the RAM and only cache to disk:
ImageCache.default.maxMemoryCost = 1
This will force Kingfisher to only use the disk cache.
How to debug
The first thing is to check that you're setting the max value on the right cache. Maybe you did create a custom cache? My example is setting the value for the default cache, the one used if no other is defined.
You may also want to manually clear the memory cache and compare the RAM occupation before and after:
ImageCache.default.clearMemoryCache()
If you think that some big image is in the memory cache when it shouldn't be, you can verify with isImageCached:
if let result = ImageCache.default.isImageCached(forKey: imageLink) {
print(result.cached)
print(result.cacheType)
}
If anyone looking for answer for downloading images explicitly and caching the same without using imageView the sample code is:
ImageDownloader.default.downloadImage(with: imgUrl, retrieveImageTask: nil, options: [], progressBlock: nil) { (image, error, url, data) in
print("Downloaded Image: \(url)")
//cache image:
if let image = image, let url = url {
ImageCache.default.store(image, forKey: url.absoluteString)
}
}
reference: https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet
Swift 5.3, Xcode 12
https://stackoverflow.com/a/44354411/10579134 , the latest version of the following
ImageCache.default.memoryStorage.config.totalCostLimit = 1 //1 in bytes

AlamofireImage cache?

I use AlamofireImage in conjunction with PromiseKit and Alamofire. I use promises to chain the download of x number of images since I want to do this synchronically. I can't seem to understand if ImageDownloader() caches automatically or if I have to add the image explicitly to the cache? The only examples I've seen so far are not using the ImageDownloader so I have a real hard time finding an answer to this.
If not - how do I add it the cache? I've tried using:
self.imageDownloader.imageCache?.addImage(image, withIdentifier: imageUrl)
But all it does is increase my memory usage for all eternity(i.e. adding the same image to the cache over and over)
I think that defining an AutoPurgingImageCache() and then using it while caching process need to solve your memory usage problem.
let photoCache = AutoPurgingImageCache(
memoryCapacity: 100 * 1024 * 1024,
preferredMemoryUsageAfterPurge: 60 * 1024 * 1024
)
You can change memoryCapacity, preferredMemoryUsageAfterPurge represent MB. To add any image in your cache, you can use like that:
photoCache.addImage(scaledImage, withIdentifier: urlString)
Also you can check this topic for more details and AlamofireImage GitHub page.
I was also using the same approach you did here. But according to the API reference the image should be added to cache automatically:
Each downloaded image is cached in the underlying NSURLCache as well as the in-memory image cache that supports image filters.
https://alamofire.github.io/AlamofireImage/Classes/ImageDownloader.html

Gif using UIImage+animtedGif class

Using this class I am trying to load a gif url into UIImageView.
The thing is , for some url's it takes 10 seconds to load, others 2 seconds.
I have tried almost anything, but still the process is too slow. 1 second would be good, but i had never succeed getting there.
I have also tried with UIWebview which had its own issues .
Here is the code :
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let fileUrl = NSURL(string:"http://45.media.tumblr.com/6785bae27b8f888fe825f0ade95796a3/tumblr_noenkbeTSw1qjmwryo1_500.gif" )
let gif = UIImage.animatedImageWithAnimatedGIFURL(fileUrl!)
dispatch_async(dispatch_get_main_queue()) {
self.player.image = gif
}
}
The problem with most of the GIF reading tools I have looked at is that they read all the data in at load time and that they allocate memory for all of the decoded frames and hold all that uncompressed data in memory at the same time. This will lead to runtime performance problems and it will crash your app and possibly your device on large/long gifs. On the issue of loading time, there is not all that much you can do since the data does need to be downloaded and read. You are also just assuming that the network cache is going to handle hitting the same GIF over and over without going to the network again, which may or may not work well for you. For a solution that addresses these issues, see this SO Question or you can also take a look at the flipboard solution here.

Determine memory limit of iOS today extension

I'm developing an iOS today extension, that can read an image from UIPasteboard and save it on disk. This process fails with large images because iOS extensions can't use much memory. To workaround this issue, I'm checking the size of the image first and try to decide, if the widget can save it or should delegate this task to its host app:
let MAXIMUM_IMAGE_SIZE_BYTES = <SomeMagicNumber>
if let clipboardImage = UIPasteboard.generalPasteboard().image {
let imageSize = CGImageGetHeight(clipboardImage.CGImage) * CGImageGetBytesPerRow(clipboardImage.CGImage)
if imageSize > MAXIMUM_IMAGE_SIZE_BYTES {
// Open host app to save image
}
else {
// Save image directly
}
}
I have the following questions:
Is my size calculation correct? I took it from this thread. I cannot instantiate a JPEG or PNG representation and read its size because of the memory limitations mentioned above.
Can I get rid of that magic number for the maximum image size in bytes? If not, are there any official specifications from Apple that I can use? I cannot test my app on every available iOS model and don't want to risk crashes on older devices.
Thanks a lot for your help!
I'm just starting to look at the memory that a notification service extension is using. I found this presentation. Might be helpful for others.
https://cocoaheads.tv/memory-use-in-extensions-by-conrad-kramer/
What was your solution to this issue?

Resources