func saveImage(image: UIImage, imageName: String, folderName: String) {
// create folder
createFolderIfNeeded(folderName: folderName)
// get path for image
guard
let url = getURLForImage(imageName: imageName, folderName: folderName),
let data = image.pngData() else { return }
// save image to path
do {
try data.write(to: url)
} catch {
print("Error saving image")
print(error.localizedDescription)
}
}
func getImage(imageName: String, folderName: String) -> UIImage? {
guard
let url = getURLForImage(imageName: imageName, folderName: folderName),
FileManager.default.fileExists(atPath: url.path) else { return nil }
return UIImage(contentsOfFile: url.path)
}
private func getCoinImage() {
if let image = fileManager.getImage(imageName: coin.id, folderName: folderName) {
self.image = image
print("Retrieved image from File Manager")
} else {
downloadCoinImage()
print("Downloading image now")
}
}
import Foundation
import SwiftUI
class LocalFileManager {
static let shared = LocalFileManager()
private init() {}
private func getURLForFolder(folderName: String) -> URL? {
guard let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return nil }
return url.appendingPathComponent(folderName)
}
private func createFolderIfNeeded(folderName: String) {
guard let url = getURLForFolder(folderName: folderName) else { return }
if !FileManager.default.fileExists(atPath: url.path) {
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
} catch {
print("Error creating folder")
print(error.localizedDescription)
}
}
}
private func getURLForImage(imageName: String, folderName: String) -> URL? {
guard let folderURL = getURLForFolder(folderName: folderName) else { return nil }
return folderURL.appendingPathComponent(imageName + ".png")
}
func saveImage(image: UIImage, imageName: String, folderName: String) {
// create folder
createFolderIfNeeded(folderName: folderName)
// get path for image
guard
let url = getURLForImage(imageName: imageName, folderName: folderName),
let data = image.pngData() else { return }
// save image to path
do {
try data.write(to: url)
} catch {
print("Error saving image")
print(error.localizedDescription)
}
}
func getImage(imageName: String, folderName: String) -> UIImage? {
guard
let url = getURLForImage(imageName: imageName, folderName: folderName),
FileManager.default.fileExists(atPath: url.path) else { return nil }
return UIImage(contentsOfFile: url.path)
}
}
id
에 따른 폴더, 파일이 존재하는지에 따라 URL을 리턴 가능import Foundation
import SwiftUI
import Combine
class CoinImageService {
@Published var image: UIImage? = nil
private var imageSubscription: AnyCancellable?
private let coin: CoinModel
private let fileManager = LocalFileManager.shared
private let folderName = "coin_images"
init(coin: CoinModel) {
self.coin = coin
getCoinImage()
}
private func getCoinImage() {
if let image = fileManager.getImage(imageName: coin.id, folderName: folderName) {
self.image = image
print("Retrieved image from File Manager")
} else {
downloadCoinImage()
print("Downloading image now")
}
}
private func downloadCoinImage() {
guard let url = URL(string: coin.image) else { return }
imageSubscription = NetworkingManager
.download(with: url)
.tryMap({ data -> UIImage? in
return UIImage(data: data)
})
.sink(receiveCompletion: NetworkingManager.handleCompletion,
receiveValue: { [weak self] image in
if
let folderName = self?.folderName,
let coin = self?.coin,
let image = image {
self?.image = image
self?.fileManager.saveImage(image: image, imageName: coin.id, folderName: folderName)
self?.imageSubscription?.cancel()
}
})
}
}
sink
단에서 파일 매니저 서비스를 통해 해당 데이터를 저장반복적으로 사용할 데이터가 아니라면 파일 매니저보다는 NSCache를 사용하는 게 보다 이롭다!