5

I have an app where the user takes a picture and once the picture is taken it should be saved to UserDefaults. I keep getting this error:

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

I've searched through documentation and posts on here, but nothing helps. This is my code.

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
    }
0

2 Answers 2

12

edit/update:

Xcode 10.1 • Swift 4.2.1 or later

It is not a good idea to store images at NSUserDefaults but if you really want to do it you need to store is as NSData.

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects

I recommend saving it locally to disk at the Documents Folder. If you really want to save it to NSUserDefaults, I recommend using just for small images and do it at your own risk :) You can do as follow:

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] ?? []
    }
}

Testing:

let image = UIImage(data: try! Data(contentsOf: URL(string: "https://i.sstatic.net/Xs4RX.jpg")!))!
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
}
Sign up to request clarification or add additional context in comments.

4 Comments

Leo Dabus, Can you please check my question i think you can solve it. stackoverflow.com/questions/38035210/appending-images-in-array Thanks
just save them to the documentsDirectory or to your application support directory. UserDefaults are not meant to store images
Could you tell me what's the disadvantage of saving image to NSUserDefault?
Property lists are not meant to store images. Why would you need to save them inside a plist file instead of writing it straight to disk?
3

Saving blob data in NSUserDefaults will result a huge performance penalty for you app. You have two options:

  1. Save image in cache folder as a file and use NSUserDefaults to store their path
  2. Use CoreData, SQLite or Realm databases to store images. Data structure of your data will determine which one is more appropriate.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.