I'm trying to build a Swift app that will query my API server for data related to a food item... because there are so many different food items available, I only want to store the image on the device when the user has chosen to do so. For this I am trying to use SVGKit to side-load in SVG images. To store them I'd like to use Core Data. I'm also using SwiftyJSON to parse the incoming data. Disclaimer: I'm pretty new at Swift and iOS development.
I have SVGKit set up, and everything else about my request seems to work fine (the data does return successfully, and I don't have any issues storing everything except the SVGKImage).
The following is inside of a function and already has a managed object context:
var request = NSMutableURLRequest(URL: NSURL(string: "\(apiImageURLBase)/\(query)")!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
let retrievedData = JSON(data: data, options: nil, error: nil)
if let imageName = retrievedData["name"].string {
let imageSVGData = retrievedData["data"].string
let imageColor = UIColor(hexString: retrievedData["color"].string)
let svgParse: SVGKParser = SVGKParser(source: SVGKSource(inputSteam: NSInputStream(data: imageSVGData!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!)))
svgParse.addDefaultSVGParserExtensions()
let imageSVG = SVGKImage(parsedSVG: svgParse.parseSynchronously(), fromSource: nil)
FoodImage.createInManagedObjectContext(managedObjectContext!, name: imageName, added: NSDate(), image: imageSVG, color: imageColor!)
}
}
This is how I've set up my managed object and it's save method:
class FoodImage: NSManagedObject {
@NSManaged var name: String
@NSManaged var added: NSDate
@NSManaged var image: SVGKImage
@NSManaged var color: UIColor
class func createInManagedObjectContext(context: NSManagedObjectContext, name: String, added: NSDate, image: SVGKImage, color: UIColor) -> NSManagedObject {
let entity = NSEntityDescription.entityForName("FoodImage", inManagedObjectContext: context)
let item = FoodImage(entity: entity!, insertIntoManagedObjectContext: context)
item.name = name
item.added = added
item.image = image
item.color = color
if !context.save(nil) {
println("Could not save.")
}
return item
}
}
The issue I'm having is right at if !context.save(nil)
when I perform the save I get the following error:
-[SVGKImage encodeWithCoder:]: unrecognized selector sent to instance 0x16eea720
*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SVGKImage encodeWithCoder:]: unrecognized selector sent to instance 0x16eea720'
I really don't know enough about memory allocation to be able to diagnose this, and my initial thought was that Swift handled allocation for the most part? Anyways, if anyone knows what I can do to solve this I would really appreciate it!
The error is not about memory allocation. You can store transformable attributes in core data only if and when NSCoding is implemented for the attribute's class. I see SVGImage does not implement NSCoding. Thus if you want to store SVGImage you can make a subclass MySVGImage (or make a category SVGImage+Coding) of SVGImage and then implement NSCoding protocol. To make SVGImage serializable might be difficult task or not practicable or even not be possible. It depends on SVGImage. So you might think about storing only information of SVGImage object that you really want to be stored via core data (like UIImage data).