You need to enable JavaScript to run this app. Swift中修改JSON字段值实现用户相册选图更新头像的方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

Swift中修改JSON字段值实现用户相册选图更新头像的方案咨询

iOS端个人资料头像修改功能实现方案

现有代码核心问题

  • 选图回调逻辑重复冗余,没有对选中图片做压缩处理,大图上传失败概率极高
  • 上传回调中存在严重的类型转换错误:直接将服务器返回的字符串类型的profileImage字段强转为UIImage类型,会直接触发崩溃
  • 上传成功后没有更新本地存储的用户信息里的profileImage字段,下次打开APP头像还是会显示旧的
  • 所有UI更新和数据存储操作没有切到主线程执行,URLSession回调默认在后台队列,直接操作UI会出现异常
  • 没有错误处理逻辑,上传失败、接口鉴权失败、返回数据格式错误等场景没有任何提示和降级处理
  • 直接使用相册返回的本地文件路径作为上传文件名,无实际意义且可能出现命名冲突

修正后的完整实现代码

1. 选图回调优化(去除重复逻辑)

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    // 统一获取选中图片,优先取编辑后版本
    guard let selectedImage = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage else {
        dismiss(animated: true)
        return
    }
    // 先更新本地UI,即时给用户反馈
    profileImage.image = selectedImage
    // 生成随机文件名避免重名
    let fileName = "profile_\(UUID().uuidString).jpeg"
    // 调用上传逻辑
    uploadImage(paramName: "image", fileName: fileName, image: selectedImage)
    dismiss(animated: true)
}

2. 图片上传逻辑修正

func uploadImage(paramName: String, fileName: String, image: UIImage) {
    guard let url = URL(string: "https://api.offernews.co/api/user") else { return }
    let boundary = UUID().uuidString
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "PATCH"
    
    // 接口需要鉴权的话打开下方注释,替换成你自己的用户token
    // urlRequest.setValue("Bearer 你的用户登录token", forHTTPHeaderField: "Authorization")
    urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
    var data = Data()
    // 拼接表单参数
    data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
    data.append("Content-Disposition: form-data; name=\"\(paramName)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
    data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
    // 压缩图片到0.5质量,可根据需求调整,头像场景0.3-0.7都足够清晰
    if let compressedImageData = image.jpegData(compressionQuality: 0.5) {
        data.append(compressedImageData)
    }
    data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
    
    URLSession.shared.uploadTask(with: urlRequest, from: data) { [weak self] responseData, response, error in
        // 切到主线程处理UI和本地数据更新
        DispatchQueue.main.async {
            guard let self = self, error == nil, let responseData = responseData else {
                // 这里可自定义上传失败的提示,比如弹toast
                print("上传失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            do {
                guard let userJson = try JSONSerialization.jsonObject(with: responseData) as? [String: Any] else {
                    print("接口返回数据格式错误")
                    return
                }
                // 取服务器返回的新头像路径
                guard let newProfileImagePath = userJson["profileImage"] as? String else {
                    print("返回数据无头像字段")
                    return
                }
                // 更新本地存储的用户信息中的profileImage字段
                // 下方的currentUser替换为你自己存储用户信息的key
                if var localUser = UserDefaults.standard.dictionary(forKey: "currentUser") {
                    localUser["profileImage"] = newProfileImagePath
                    UserDefaults.standard.set(localUser, forKey: "currentUser")
                }
                print("头像更新成功,新路径:\(newProfileImagePath)")
            } catch {
                print("JSON解析失败:\(error.localizedDescription)")
            }
        }
    }.resume()
}

额外注意事项

  • 如果服务器返回的profileImage是相对路径,需要拼接上你的服务器域名前缀才能正常加载显示
  • 图片压缩率可以根据业务需求调整,JPEG格式比PNG格式体积小很多,头像场景优先用JPEG
  • 建议给上传过程加loading提示,避免用户重复点击提交

内容的提问来源于stack exchange,提问作者Ali kazemi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 21:33:00