While Strings appears to be fine I'm having some trouble storing Integers into Core Data. Following tutorials and reading available information out there doesn't seem to be helping me who has no Objective-C background. (Swift seemed like a straight forward language like the languages I'm fluent with PHP/OOPHP/JavaScript/VBScript/... thus I started playing with it and so far have been able to do everything I wanted, almost)
What I want to do now is, to receive the JSON data and store it into Core Data
Here's my Core Data
Entity name: Category
Its Attributes:
id Int16
title String
description String
My Swift model? file: Category.swift
import CoreData
class Category: NSManagedObject {
@NSManaged var id: Int //should I declare this as Int16?
@NSManaged var title: String
@NSManaged var description: String
}
I'm using SwiftyJASON extension? and NSURLSession protocol? to get the data and to parse it as follow:
import UIKit
import CoreData
class ViewController: UIViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
func fetchData() {
var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category")
var session = NSURLSession.sharedSession()
session.dataTaskWithURL(url, completionHandler: {(data, response, error) in
// parse data into json
let json = JSONValue(data)
let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: self.managedObjectContext)
let category = Category(entity: entityDescription, insertIntoManagedObjectContext: self.managedObjectContext)
for item in json.array! {
category.id = item["id"].string!.toInt()! //goes KABOOM!
category.title = item["title"].string!
category.description = item["description"].string!
managedObjectContext?.save(nil)
}
dispatch_async(dispatch_get_main_queue()) {
// do something
}
}).resume()
}
}
Let's assume the JASON data is:
[{"id":"1","title":"cat1","description":"blabala one"},{"id":"2","title":"cat2","description":"blabala two"}]
At line where it says category.id = item["id"].string!.toInt()!
xCode goes KABOOM, what am I doing wrong here?
Notes/More questions:
I tried changing id type within Core Data to Int32 and then declaring it as just Int in the model (and not Int16 or Int32) which reduced some errors but xCode still crashes
Probably the way I'm looping stuff is not the best way to do this, what's the better way of storing array of data into core data at once?
Most of the tutorials I've seen there's no id's for Entities(tables), am I missing something here?
References:
EDIT > Working code:
Category.swift model file which can be auto generated using File>New>File>iOS>Core Data>NSManagedObject subclass [swift, no need for bridging header but you need to manually add @objc line as below]
import CoreData
@objc(Category) //Wouldn't work without this
class Category: NSManagedObject {
@NSManaged var id: NSNumber //has to be NSNumber
@NSManaged var title: String
@NSManaged var mydescription: String //"description" is reserved so is "class"
}
ViewController.swift
import UIKit
import CoreData
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
func fetchData() {
var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category")
var session = NSURLSession.sharedSession()
session.dataTaskWithURL(url, completionHandler: {(data, response, error) in
let json = JSONValue(data)
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext //this line had to be moved here
let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: managedObjectContext)
for item in json.array! {
let category = Category(entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext) //this line has to be in inside for loop
category.id = item["id"].string!.toInt()!
category.title = item["title"].string!
category.mydescription = item["description"].string!
managedObjectContext?.save(nil)
}
dispatch_async(dispatch_get_main_queue()) {
// do something
}
}).resume()
}
}
Sample fetching data code:
func requestData() {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Category")
request.returnsObjectsAsFaults = false
var results:NSArray = context.executeFetchRequest(request, error: nil)
//println(results)
for category in results {
var cat = category as Category
println("\(cat.id),\(cat.title),\(cat.mydescription)")
}
}
P.S. Make sure to Clean your project and delete the app from simulator after changing Model
Scalar types (integers, floats, booleans) in core data are broken in the current Swift beta (5). Use NSNumber for the properties, and file a radar.
object.intProperty = NSNumber(int:Int(item["id"] as String))
(Typed on the phone, so sorry if that's wrong, and I know it's disgusting code - hence, file a radar!)
Or, in your specific case, looking at the JSON, use String. Those IDs are coming in as strings anyway.
Updated for Swift 2
If your JSON data is really of type [[String:String]]
, you can use the following code in order to set category.id
:
if let unwrappedString = item["id"], unwrappedInt = Int(unwrappedString) {
category.id = unwrappedInt
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With