FileManager/本地文件增删改查, Cache/图像缓存处理 的操作

1. FileManager 本地文件管理器,增删改查文件

  1.1 实现

// 本地文件管理器
class LocalFileManager{
    // 单例模式
    static let instance = LocalFileManager()
    let folderName = "MyApp_Images"
    
    init() {
        createFolderIfNeeded()
    }
    
    // 创建特定应用的文件夹
    func createFolderIfNeeded(){
        // 创建文件夹路径
        guard let path = FileManager
            .default
            .urls(for: .cachesDirectory, in: .userDomainMask)
            .first?
            .appendingPathComponent(folderName)
            .path else {
            return
        }
        
        // 判断文件夹是否存在,不存在,则创建文件夹路径
        if !FileManager.default.fileExists(atPath: path){
            do {
                try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true)
                print("Success create folder.")
            } catch let error {
                print("Error creating folder. (error)")
            }
        }
    }
    
    // 删除特定应用的文件夹
    func deleteFolder(){
        // 创建文件夹路径
        guard let path = FileManager
            .default
            .urls(for: .cachesDirectory, in: .userDomainMask)
            .first?
            .appendingPathComponent(folderName)
            .path else {
            return
        }
        
        do {
            try FileManager.default.removeItem(atPath: path)
            print("Success deleting filder.")
        } catch let error {
            print("Error deleting folder. (error)")
        }
    }
    
    // 保存图片
    func saveImage(image: UIImage, name: String) -> String{
        // 压缩图片质量
        //image.jpegData(compressionQuality: 1.0)
        // 获取数据和文件路径
        guard
            let data =  image.pngData(),
            let path = getPathForImage(name: name)
        else{
            return "Error getting data."
        }
        
        do{
            // 文件写入数据
            try data.write(to: path)
            return "Success saving."
        }catch let error{
            return "Error saving: (error.localizedDescription)"
        }
    }
    
    // 获取图片
    func getImage(name: String) -> UIImage?{
        // 获取文件路径 absoluteString,并检查文件是否存在
        guard let path = getPathForImage(name: name)?.path,
              FileManager.default.fileExists(atPath: path) else{
            print("Error getting path.")
            return nil
        }
        return UIImage(contentsOfFile: path)
    }
    
    // 删除图片
    func deleteImage(name: String) -> String{
        // 获取文件路径,并检查文件是否存在
        guard let path = getPathForImage(name: name)?.path,
              FileManager.default.fileExists(atPath: path) else{
            return "Error getting path."
        }
        do {
            // 删除文件
            try FileManager.default.removeItem(atPath: path)
            return "Successfully deleted."
        } catch let error {
            return "Error deleting image: (error)"
        }
    }
    
    // 获取文件路径
    func getPathForImage(name: String) -> URL?{
        // 文档目录
        //let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        // 缓存目录
        //let directory2 = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
        // 临时目录
        //let directory3 = FileManager.default.temporaryDirectory
        // 拼接路径
        //let path = directory2?.appendingPathComponent("(name).png")
        guard
            let path = FileManager
                .default
                .urls(for: .cachesDirectory, in: .userDomainMask)
                .first?
                .appendingPathComponent(folderName)
                .appendingPathComponent("(name).png") else {
            print("Error getting data.")
            return nil
            
        }
        print(path)
        return path
    }
}

class FileManagerViewModel: ObservableObject{
    @Published var image: UIImage? = nil
    let imageName: String = "steve-jobs"
    let localManager  = LocalFileManager.instance
    @Published var infoMessage: String  = ""
    
    init() {
        getImageFromAssetsFoler()
        //getImageFromFileManager()
    }
    // 获取图片,在资源目录
    func getImageFromAssetsFoler(){
        image = UIImage(named: imageName)
    }
    // 获取图像,文件管理器
    func getImageFromFileManager(){
        image = localManager.getImage(name: imageName)
    }
    // 保存图像
    func saveImage(){
        guard let image = image else { return }
        infoMessage = localManager.saveImage(image: image, name: imageName)
    }
    // 删除图像
    func deleteImage(){
        infoMessage = localManager.deleteImage(name: imageName)
        localManager.deleteFolder()
    }
}

/// 文件管理器
struct FileManagerBootcamp: View {
    @StateObject var viewModel = FileManagerViewModel()
    
    var body: some View {
        NavigationView {
            VStack {
                if let image = viewModel.image {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 200, height: 200)
                        .clipped()
                        .cornerRadius(10)
                }
                
                HStack {
                    Button {
                        viewModel.saveImage()
                    } label: {
                        Text("Save to Fm")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .padding(.horizontal)
                            .background(Color.accentColor)
                            .cornerRadius(10)
                    }
                    
                    Button {
                        viewModel.deleteImage()
                    } label: {
                        Text("Delete from Fm")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .padding(.horizontal)
                            .background(Color.red)
                            .cornerRadius(10)
                    }
                }
                
                Text(viewModel.infoMessage)
                    .font(.largeTitle)
                    .fontWeight(.semibold)
                    .foregroundColor(.purple)
                //.padding(.top, 20)
    
                Spacer()
            }
            .navigationTitle("File Manager")
        }
    }
}

  1.2 效果图

2. Cache 图像缓存处理操作

  2.1 实现

// 缓存管理器
class CacheManager {
    // 单例模式
    static let instance = CacheManager()
    
    private init() {}
    
    // 计算型属性 图像缓存
    var imageCache: NSCache<NSString, UIImage> = {
        let cache = NSCache<NSString, UIImage>()
        // 容纳最大对象的数量
        cache.countLimit = 100
        // 容纳最大值
        cache.totalCostLimit = 1024 * 1024 * 100 // 100mb
        return cache
    }()
    
    // 添加图像
    func add(image: UIImage, name: String) -> String{
        imageCache.setObject(image, forKey: name as NSString)
        return "Added to cache!"
    }
    
    // 移除图像
    func remove(name: String) -> String{
        imageCache.removeObject(forKey: name as NSString)
        return "Removed from cache"
    }
    
    // 获取图像
    func get(name: String) -> UIImage?{
        return imageCache.object(forKey: name as NSString)
    }
}

// 缓存 ViewModel
class CacheViewModel: ObservableObject{
    @Published var startingImage: UIImage? = nil
    @Published var cachedImage: UIImage? = nil
    @Published var infoMessage: String = ""
    
    let imageName = "steve-jobs"
    let manager = CacheManager.instance
    
    init() {
        getImageFromAssetsFolder()
    }
    
    // 获取资源文件中图像
    func getImageFromAssetsFolder(){
        startingImage = UIImage(named: imageName)
    }
    
    // 保存图像
    func saveToCache(){
        guard let image = startingImage else { return }
        infoMessage = manager.add(image: image, name: imageName)
    }
    
    // 移除图像
    func removeFromCache(){
        infoMessage = manager.remove(name: imageName)
    }
    
    // 获取缓存图像
    func getFromCache(){
        if let returnedImage = manager.get(name: imageName){
            cachedImage = returnedImage
            infoMessage = "Got image from cache"
        }else{
            cachedImage = nil
            infoMessage = "Image not found in cache"
        }
    }
}

// 缓存管理
struct CacheBootcamp: View {
    @StateObject var viewModel = CacheViewModel()
    
    var body: some View {
        NavigationView {
            VStack {
                if let image = viewModel.startingImage{
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 200, height: 200)
                        .clipped()
                        .cornerRadius(10)
                }
                
                Text(viewModel.infoMessage)
                    .font(.largeTitle)
                    .fontWeight(.semibold)
                    .foregroundColor(Color.purple)
                
                HStack {
                    Button {
                        viewModel.saveToCache()
                    } label: {
                        Text("Save to Cache")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.accentColor)
                            .cornerRadius(10)
                    }
                    
                    Button {
                        viewModel.removeFromCache()
                    } label: {
                        Text("Delete from Cache")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.red)
                            .cornerRadius(10)
                    }
                }
                
                Button {
                    viewModel.getFromCache()
                } label: {
                    Text("Get from Cache")
                        .font(.headline)
                        .foregroundColor(.white)
                        .padding()
                        .background(Color.green)
                        .cornerRadius(10)
                }
                
                if let image = viewModel.cachedImage{
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 200, height: 200)
                        .clipped()
                        .cornerRadius(10)
                }
                
                Spacer()
            }
            .navigationTitle("Cache Bootcamp")
        }
    }
}

  2.2 效果图