Reputation: 7537
I want to be able to save an array, cardImages
, that contains UIImages via SwiftyUserDefaults.
Desired Behavior
Here is the exact desired behavior:
Save an array of UIImages to NSUserDefaults via the SwiftyUserDefault library
Retrieve the images later
Code This is stripped down to very little code
var newPhotoKey = DefaultsKey<NSArray>("image")//Setting up the SwiftyUserDefaults Persisted Array
cardImages = [(UIImage(named: "MyImageName.jpg")!)] //This array contains the default value, and will fill up with more
Defaults[theKeyForStoringThisArray] = cardImages //This is the persisted array in which the array full of images should be stored. WHERE THE ERROR HAPPENS
var arrayToRetreiveWith = Defaults[theKeyForStoringThisArray] as! [UIImage] //To Retreive
Error
I get the following error:
Attempt to set a non-property-list object ( ", {300, 300}" ) as an NSUserDefaults/CFPreferences value for key image *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object ( ", {300, 300}" ) for key image'
Thanks!
Upvotes: 2
Views: 675
Reputation: 3433
The error message is clear actually. UIImage is not a propertylist so you need to change it to a row data first. I'll put example below but FYI saving big data like images using NSUserDefaults is really not recommended. I'd use NSFileManager and put it in the user documents directory. anyway
var newPhotoKey = DefaultsKey<NSArray>("image")
cardImages = [(UIImage(named: "MyImageName.jpg")!)]
var cardImagesRowdataArray: NSData = []
for image in cardImages {
let imageData = UIImageJPEGRepresentation(image, 1.0)
cardImagesRowdataArray.append(imageData)
}
Defaults[theKeyForStoringThisArray] = cardImagesRowdataArray
var arrayToRetreiveWith = Defaults[theKeyForStoringThisArray] as! [NSData]
// here you can use UIImage(data: data) to get it back
If you don't insist on using SwiftyUserDefaults, you can save it in the user documents directory, here is how to do it
func saveImage(image: UIImage){
if let imageData = UIImageJPEGRepresentation(image, 1.0) {
let manager = NSFileManager()
if let docUrl = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first{
let uniqueName = NSDate.timeIntervalSinceReferenceDate()
let url = docUrl.URLByAppendingPathComponent("\(uniqueName).jpg")
imageData.writeToURL(url, atomically: true)
}
}
}
Upvotes: 3
Reputation: 386038
The value of a user default must be a property list. A property list is
String
or NSString
),NSData
,NSDate
),NSNumber
),NSNumber
),A UIImage
is none of those, so a UIImage
is not a property list and cannot be part of a property list.
You need to convert your image to an NSData
to store it in a user default. Since a UIImage
contains some properties (like scale
and imageOrientation
) in addition to raw pixel data, the easiest way to convert a UIImage
to an NSData
with no loss is by creating an archive:
let cardImage: UIImage? = someImage()
let cardImageArchive: NSData = NSKeyedArchiver.archivedDataWithRootObject(cardImage!)
Now you can store cardImageArchive
in a larger property list that you can store as a user default.
Later, when you need to recreate the image from the data, do this:
let cardImageArchive: NSData = dataFromUserDefaults()
let cardImage: UIImage = NSKeyedUnarchiver.unarchiveObjectWithData(cardImageArchive) as! UIImage
Upvotes: 2