You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI如何将选中图片保存到CoreData并在其他视图读取展示

实现方案

1. 选中图片后本地存储逻辑

我们优先把头像存储到沙盒Documents目录,相比存UserDefaults性能更好,也适合存储图片这类二进制数据。首先新增图片管理工具类:

import UIKit

class ProfileImageManager {
    static let shared = ProfileImageManager()
    private let saveFileName = "user_profile_image.jpg"
    
    // 保存头像到本地
    @discardableResult
    func saveProfileImage(_ image: UIImage) -> Bool {
        // 转成JPG格式,压缩质量0.8兼顾清晰度和体积
        guard let imageData = image.jpegData(compressionQuality: 0.8),
              let docPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
            return false
        }
        let saveUrl = docPath.appendingPathComponent(saveFileName)
        do {
            try imageData.write(to: saveUrl)
            return true
        } catch {
            print("头像保存失败:\(error.localizedDescription)")
            return false
        }
    }
    
    // 读取本地存储的头像
    func loadProfileImage() -> UIImage? {
        guard let docPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
            return nil
        }
        let saveUrl = docPath.appendingPathComponent(saveFileName)
        do {
            let imageData = try Data(contentsOf: saveUrl)
            return UIImage(data: imageData)
        } catch {
            print("头像读取失败:\(error.localizedDescription)")
            return nil
        }
    }
}

接下来修改你现有代码,监听图片选择完成自动触发保存:

image!
    .resizable()
    .aspectRatio(contentMode: .fill)
    .frame(width: 150, height: 150)
    .clipShape(Circle())
    .overlay(Circle().stroke(Color.white, lineWidth: 4))
    .shadow(radius: 10)
    .onTapGesture { self.shouldPresentActionScheet = true }
    .sheet(isPresented: $shouldPresentImagePicker) {
        SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
    }
    .actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
        ActionSheet(title: Text("选择方式"), message: Text("请选择上传头像的方式"), buttons: [
            ActionSheet.Button.default(Text("相机"), action: {
                self.shouldPresentImagePicker = true
                self.shouldPresentCamera = true
            }),
            ActionSheet.Button.default(Text("相册"), action: {
                self.shouldPresentImagePicker = true
                self.shouldPresentCamera = false
            }),
            ActionSheet.Button.cancel()
        ])
    }
    // 新增:监听图片变化自动保存
    .onChange(of: image) { newImage in
        guard let validImage = newImage else { return }
        let saveResult = ProfileImageManager.shared.saveProfileImage(validImage)
        if saveResult {
            // 可在此处添加保存成功的toast提示
        }
    }

2. 其他视图读取展示头像

直接调用工具类的读取方法即可,示例代码如下:

struct ProfileDisplayView: View {
    @State private var userAvatar: UIImage? = ProfileImageManager.shared.loadProfileImage()
    
    var body: some View {
        VStack {
            if let avatar = userAvatar {
                Image(uiImage: avatar)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 80, height: 80)
                    .clipShape(Circle())
            } else {
                // 无头像时显示占位图
                Image(systemName: "person.circle.fill")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 80, height: 80)
                    .foregroundColor(.gray)
            }
        }
        // 每次进入页面刷新头像,保证显示最新版本
        .onAppear {
            userAvatar = ProfileImageManager.shared.loadProfileImage()
        }
    }
}

注意事项

  • 不需要存到系统相册,上述本地存储方式仅对当前App可见,卸载App时会同步删除
  • 如果需要头像更新后所有关联页面自动刷新,可以结合NotificationCenter发通知,不需要每个页面单独处理
  • 压缩质量参数可根据需求调整,范围0~1,数值越大图片越清晰、体积越大

内容的提问来源于stack exchange,提问作者Raw Bit Rabbit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 17:06:02