Reputation:
I am trying to download and play videos in a tableView like Instagram, vine or even facebook.
What I am trying to achieve is a tableView where I display the videos and they auto download and play while scrolling. Like Instagram...
So far I have managed most of that, but what I would like to change is the fact that every time I view a cell the video gets downloaded again and again.... Surely there must be a way to cache videos, or only download the same video once.... Like you do with SDWebImages for images.
Also at the moment with it download every time I view the cell, the scrolling is terrible as you can imagine.
Now I cannot seem to figure out how Instagram does it, but I am 100% sure they don't download the same video more than once!!
If anyone has and advice or ideas, I'd love to hear them!!
Many thanks in advance.
Upvotes: 16
Views: 16043
Reputation: 1259
Using Haneke, I wasn't able to retrieve file path for cached video. I handled it by saving video in cached directory.
public enum Result<T> {
case success(T)
case failure(NSError)
}
class CacheManager {
static let shared = CacheManager()
private let fileManager = FileManager.default
private lazy var mainDirectoryUrl: URL = {
let documentsUrl = self.fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
return documentsUrl
}()
func getFileWith(stringUrl: String, completionHandler: @escaping (Result<URL>) -> Void ) {
let file = directoryFor(stringUrl: stringUrl)
//return file path if already exists in cache directory
guard !fileManager.fileExists(atPath: file.path) else {
completionHandler(Result.success(file))
return
}
DispatchQueue.global().async {
if let videoData = NSData(contentsOf: URL(string: stringUrl)!) {
videoData.write(to: file, atomically: true)
DispatchQueue.main.async {
completionHandler(Result.success(file))
}
} else {
DispatchQueue.main.async {
completionHandler(Result.failure(NSError.errorWith(text: "Can't download video")))
}
}
}
}
private func directoryFor(stringUrl: String) -> URL {
let fileURL = URL(string: stringUrl)!.lastPathComponent
let file = self.mainDirectoryUrl.appendingPathComponent(fileURL)
return file
}
}
Sample usage of this class looks like this:
CacheManager.shared.getFileWith(stringUrl: "http://techslides.com/demos/sample-videos/small.mp4") { result in
switch result {
case .success(let url):
// do some magic with path to saved video
case .failure(let error):
// handle errror
}
}
Upvotes: 30
Reputation: 1872
great question. You're best bet is to use something open-source and 3rd party on Github. I use them solely for images, but I believe they will load and cache videos for you as well. Here are the links to some popular ones...
https://github.com/onevcat/Kingfisher https://github.com/Haneke/HanekeSwift There is also a good list of libraries you might find useful... https://github.com/Wolg/awesome-swift
Hope this helps!
Upvotes: -1