UserDefaults to Image code builds, but crashes when ran

65 Views Asked by At

I am coming from reading code from a ton of StackOverFlow posts for what seems to be a rather simple procedure, but when I try to implement what I've learned in my own code it fails.

In my "ViewController" didSelectRowAt function, I initialized the user defaults

let song = tableViewData[indexPath.section].songData[indexPath.row - 1]
let songImage = song.artwork

UDM.shared.defaults.setValue(song.title, forKey: "name")
UDM.shared.songCover.setValue(songImage, forKey: "cover")

Then created a class to hold the UserDefaults

class UDM{
static let shared = UDM()

//let defaults = UserDefaults(suiteName: com.CTMVenturesInc.MusicTesters.saved.data)
let defaults = UserDefaults()
let songCover = UserDefaults()

//other funcs
}

Following that in my "TealViewController" I created the label & image element

@IBOutlet var label: UILabel!
@IBOutlet var coverImage: UIImageView!

Lastly in the viewDidLoad of TealViewController I set the values

if let value = UDM.shared.defaults.value(forKey: "name") as? String{
    label.text = value
}
    
if let value = UDM.shared.songCover.value(forKey: "cover") as? MPMediaItemArtwork{
    coverImage.image = value.image(at: CGSize(width: 400, height: 400))
}

This runs and works perfectly with just the text default, but when I try to include the image code I get this run error

Thread 1: "Attempt to insert non-property list object <MPConcreteMediaItemArtwork: 0x2830c4c80> for key cover"

So I found this post Save images in NSUserDefaults? and tried to implement in my view controller replacing this

UDM.shared.songCover.setValue(songImage, forKey: "cover")

with this

[UDM.shared.songCover.set: UIImagePNGRepresentation(songImage) forKey: "cover"]

But get a cannot find forKey error. I looked at this post How to pass UI image from one view controller to another? and tried this

UDM.shared.songCover.standardUserDefaults().setObject(UIImagePNGRepresentation(songImage), forKey:"cover")}

and got even more errors enter image description here

What is it that I am not putting together here?

1

There are 1 best solutions below

0
On

problem 1

The only things you can save into user defaults are NSString, NSData, NSArray, and NSDictionary (or Swift classes that are bridged to them).

MPMediaItemArtwork is not one of those; neither is UIImage.

To save something into user defaults that is not one of those, you must archive it somehow, meaning convert it (serialize it) into an NSData. You are not going to be able to do that with MPMediaItemArtwork, so you need to come up with another strategy for saving whatever it is that is important to you about this object.

Just to give an example (which seemed to be where you were heading), a UIImage derived from the MPMediaItemArtwork can be archived to an NSData, and now you can put it into user defaults.

However, that's not a very good way of saving an image; it would be better to save its data directly as a file to disk.

problem 2

User defaults is not itself some deep object where you can write into the properties of objects it already contains and your architecture of having two different properties both of which are merely instantiations of UserDefaults is very weird. Instead of passing through a second object, just make a piece of data of the right type, and call UserDefaults.standard.set... to set it by a key.