使用UserDefaults保存图像数组

5

我有一个应用程序,用户拍照后,应该将照片保存到UserDefaults中。但是我一直收到这个错误:

"cannot invoke 'setObject' with an argument list of type '(UIImage. type, forKey:[UIImage])'"

我已经查阅了文档和相关帖子,但是没有找到解决办法。这是我的代码。

let defaults = NSUserDefaults.standardUserDefaults()

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

    picker.dismissViewControllerAnimated(true, completion: nil)

    switch currentClothesSelection!{

        case "1":
            shirts.append(info[UIImagePickerControllerOriginalImage] as! UIImage)

            //this is where the error occurs
            defaults.setObject(UIImage.self, forKey: array1)

        case "2" :
            pants.append(info[UIImagePickerControllerOriginalImage] as! UIImage)
        case "3" :
            shorts.append(info[UIImagePickerControllerOriginalImage] as! UIImage)
        case "4" :
            jackets.append(info[UIImagePickerControllerOriginalImage] as! UIImage)
        case "5" :
            shoes.append(info[UIImagePickerControllerOriginalImage] as! UIImage)

        default:
         break
    }
2个回答

12

编辑/更新:

Xcode 10.1 • Swift 4.2.1 或更高版本

将图像存储在NSUserDefaults中不是一个好主意,但如果你真的想这么做,你需要将它存储为NSData。

value参数只能是属性列表对象:NSData、NSString、NSNumber、NSDate、NSArray或NSDictionary。对于NSArray和NSDictionary对象,它们的内容必须是属性列表对象

我建议将其本地保存到文档文件夹中。如果你真的想将其保存到NSUserDefaults中,我建议仅限于小型图像,并自行承担风险 :) 操作步骤如下:

extension UserDefaults {
    func set(image: UIImage?, quality: CGFloat = 0.5, forKey defaultName: String) {
        guard let image = image else {
            set(nil, forKey: defaultName)
            return
        }
        set(image.jpegData(compressionQuality: quality), forKey: defaultName)
    }
    func image(forKey defaultName:String) -> UIImage? {
        guard
            let data = data(forKey: defaultName),
            let image = UIImage(data: data)
        else  { return nil }
        return image
    }
    func set(images value: [UIImage]?, forKey defaultName: String) throws {
        guard let value = value else {
            removeObject(forKey: defaultName)
            return
        }
        try set(NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: false), forKey: defaultName)
    }
    func images(forKey defaultName: String) throws -> [UIImage] {
        guard let data = data(forKey: defaultName) else { return [] }

        let object = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
        return object as? [UIImage] ?? []
    }
}

测试:

let image = UIImage(data: try! Data(contentsOf: URL(string: "https://istack.dev59.com/Xs4RX.webp")!))!
UserDefaults.standard.set(image: image, forKey: "imageKey")
if let loadedImage = UserDefaults.standard.image(forKey: "imageKey") {
    print(loadedImage.size)  // "(719.0, 808.0)"
}

let images = [image, image]
try? UserDefaults.standard.set(images: images, forKey: "imagesKey")
if let loadedImages = try? UserDefaults.standard.images(forKey: "imagesKey") {
    print(loadedImages.count)  // 2
}

Leo Dabus,您能否帮我看一下我的问题,我认为您可以解决它。 http://stackoverflow.com/questions/38035210/appending-images-in-array谢谢。 - ZAFAR007
只需将它们保存到documentsDirectory或应用程序支持目录中即可。UserDefaults不适合存储图像。 - Leo Dabus
你能告诉我将图像保存到NSUserDefault的缺点是什么吗? - allenlinli
1
属性列表不适合存储图像。为什么要将它们保存在属性列表文件中,而不是直接写入磁盘? - Leo Dabus

3

在NSUserDefaults中保存Blob数据会导致您的应用程序出现巨大的性能损失。您有两个选择:

  1. 将图像保存到缓存文件夹中,并使用NSUserDefaults来存储它们的路径
  2. 使用CoreData、SQLite或Realm数据库来存储图像。您的数据结构将决定哪种方法更合适。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接