cant get the integer from core data atribute - ios

I have a core data model, where I added entity named CurrentLevel and an attribute called currentLevel and of int16 type. I am trying to save a simple integer into it like this:
func saveCurrentLevel(cLevel: Int16){
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("CurrentLevel",
inManagedObjectContext:
managedContext)
let curLevel = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
curLevel.setValue(NSNumber(short: cLevel), forKey: "currentLevel")
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
}
and this is my method for fetching
func fetchTheStuff() {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let fetchRequest = NSFetchRequest(entityName:"CurrentLevel")
//3
var error: NSError?
var fetchedResults =
managedContext.executeFetchRequest(fetchRequest,
error: &error) as? [NSManagedObject]
if let results = fetchedResults {
println(results)
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}
}
I need that the fetched result would be just a simple integer and I cant find a way with core data to do so. Anyone know how ad/or what I am doing wrong?

executeFetchRequest() returns an array of managed objects.
You have to get a single element (e.g. the first), then retrieve the
value of the "currentLevel" attribute (which is a NSNumber)
and finally extract the Int16:
if let results = fetchedResults {
if count(results) > 0 {
let curLevel = results[0] // NSManagedObject
if let num = curLevel.valueForKey("currentLevel") as? NSNumber {
let cLevel = num.shortValue // Int16
println(cLevel)
} else {
println("level not set")
}
} else {
println("no objects found")
}
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}
Instead of Key-Value coding with setValue/valueForKey() you can also
let Xcode create NSManagedObject subclasses. If you activate
the "use scalar properties for primitive data types" option then
you can access its
#NSManaged var currentValue: Int16
property directly.

With Objective-C you need to store the int as a NSNumber when using Core Data. So if I was using an int, I would do it like this:
coreDataClass.number = [NSNumber numberWithInt:100];
I'm not sure if it's the same with Swift though.

Related

fetching a custom object from core data into an array

I'm having trouble fetching my object from core data. Object looks like this:
class cilj: NSObject {
var imeCilja: String
var slikaCilja: String }
My entity is called Entity and has two Attributes "tekst" and "slika", both of type String. My save func is this:
func saveImage(goalName:String, imageName:String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("Entity", inManagedObjectContext:managedContext)
let thingToSaveToCD = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: managedContext)
thingToSaveToCD.setValue(globalGoalTitle, forKey: "tekst")
thingToSaveToCD.setValue(globalGoalImagePath, forKey: "slika")
do {
try managedContext.save()
print("managed to save to core data")
//5
// listaObjekata.append(cilj5) as! [cilj]
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
I use an alertController to pick up the text, and imagePicker to pick up image that I then store in documents and get the path. I store both of these in a global variables visible in the code above.
My fetch function is :
func coreDataFetch(){
//core data fetch
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let fetchRequest = NSFetchRequest(entityName: "Entity")
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [cilj]
listaObjekata = fetchedResults
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
I have been through ray wenderlich's article on Core Data, Apple's documentation, a couple of YT videos but I still seem to be missing something. I would greatly appreciate any help. Thanks !
EDIT - here is my cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell") as! cellController
let ciljZaPrikaz = listaObjekata[indexPath.item]
cell.labelText.text = ciljZaPrikaz.imeCilja ?? "no text found"
let path = getDocumentsDirectory().stringByAppendingPathComponent(ciljZaPrikaz.slikaCilja)
cell.imageToShow.image = UIImage(contentsOfFile: path)
return cell
}
You are doing correct but just missing type casting to your model. Try below:
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
if let results = fetchResults where results.count > 0 {
let entityModel = results[0] as? Entity
let tekst = entityModel.tekst
}
I would also like to add how I iterate through my return objects from core data:
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
listaObjekata.removeAll()
for i in 0...(fetchedResults.count-1) {
let enityModel = fetchedResults[i] as? Entity
let thisToArray = cilj(imeCilja: (enityModel?.tekst!)!, slikaCilja: (enityModel?.slika!)!)
listaObjekata.append(thisToArray)
}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}

saving Core Data arrays and dictionaries

referring to my previous question: Unique value of object to use in section Swift
my problem now is core data. this is code to save data following the previous code to populate section and table:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Movie", inManagedObjectContext: context)!
let movie = Movie(entity: entity, insertIntoManagedObjectContext: context)
movie.title = title.text
movie.plot = plot.text
movie.genre = genre.text
context.insertObject(movie)
do {
try context.save()
} catch {
print("Could not save movie")
}
and fetch data is:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Movie")
do {
let results = try context.executeFetchRequest(fetchRequest)
self.loadMovie = results as! [Movie]
} catch let err as NSError {
print(err.debugDescription)
}
}
but nothing I receive the error on loadMovie Line..
where am I wrong?
First of all, delete the line
context.insertObject(movie)
because the object has already been inserted in the let movie = line.
To load the movies you need to recreate the data structure using the insertMovie(movie : Movie) function.
let movies = try context.executeFetchRequest(fetchRequest) as! [Movie]
loadMovie.removeAll()
for movie in movies {
insertMovie(movie)
}
As the answer of your previous question suggested, the self.loadMovie now has type [String:[Movie]], so you should probably try casting results as [String:[Movie]].
Try self.loadMovie = results as! [String:[Movie]] instead.

iOS Optional wrapping in Swift

I'm saving an array into a model, when saving the data is not wrapped with Optional (...) however when the data is being read I get the Optional(...) wrapping around it.
Appreciate your help.
saveOperativesInModel: Test Name
saveOperativesInModel: test team 999
getOperativesFromModel: Optional(Test Name)
getOperativesFromModel: Optional(test team 999)
func saveOperativesInModel() {
if (self.operativesResult?.operativesList.count > 0) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Operatives", inManagedObjectContext: managedContext)
// Remove all records in entity
let fetchRequest = NSFetchRequest()
fetchRequest.entity = entity
fetchRequest.includesPropertyValues = false
var error:NSError?
if let results = managedContext.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject] {
for result in results {
managedContext.deleteObject(result)
}
}
var item: NSManagedObject!
//var itemInArray: Operative!
if let operativesList = self.operativesResult?.operativesList {
self.operativesTable.removeAll()
for itemInArray in operativesList {
item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
item.setValue(itemInArray.id, forKey: "id")
item.setValue(itemInArray.firstName, forKey: "firstName")
item.setValue(itemInArray.lastName, forKey: "lastName")
item.setValue(itemInArray.mobile, forKey: "mobile")
var error: NSError?
if !managedContext.save(&error) {
println("saveOperativesInModel - Could not save \(error), \(error?.userInfo)")
} else {
self.operativesTable.append(item!)
println("saveOperativesInModel: \(itemInArray.firstName)")
}
}
}
//println("saveOperativesInModel : \(operativesTable.count) items")
let fetchRequest1: NSFetchRequest! = NSFetchRequest(entityName:"Operatives")
var error1: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest1, error: &error1) as? [NSManagedObject]
if let operativesTable = fetchedResults {
if operativesTable.count > 0 {
println("getOperativesFromModel : \(operativesTable.count)")
}
if operativesTable.count > 0 {
for item in operativesTable {
let operative: Operative! = Operative()
operative.id = String (stringInterpolationSegment: item.valueForKey("id"))
operative.firstName = String (stringInterpolationSegment: item.valueForKey("firstName"))
operative.lastName = String (stringInterpolationSegment: item.valueForKey("lastName"))
println("getOperativesFromModel: \(operative.firstName)")
}
}
} else {
println("Could not fetch \(error1), \(error1!.userInfo)")
}
}
}
The firstName attribute from Operative class should be an optional (probably declared like this var firstName: String?. So if you're sure you have a string inside firstName, you can replace your print line with this:
println("getOperativesFromModel: \(operative.firstName!)")

Getting types from NSManagedObject

It's my first time using core data. I'm trying to use it to store basic info about my user (if he's logged in through parse.com). So far so good with writing to core data, however, I'm struggling to get the data back. I'm able to print out the data as a [NSManagedObject], but I can't get the data into the different types ( String, Bool, and UIImage). How can I do this?
Saving Data
func saveUser(username : String, proPic : UIImage?){
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let entity = NSEntityDescription.entityForName("User",
inManagedObjectContext:
managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
//3
person.setValue(username, forKey: "username")
person.setValue(true, forKey: "isLoggedIn")
person.setValue(proPic, forKey: "profilePic")
//4
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
}
Getting Data Back
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let fetchRequest = NSFetchRequest(entityName:"UserInfo")
//3
var error: NSError?
let fetchedResults =
managedContext.executeFetchRequest(fetchRequest,
error: &error) as? [NSManagedObject]
You can use valueForKey similar way you used setValue before. Then you need to deal with the fact that it returns AnyObject.
Another option is to generate custom NSManagedObject subclass. Select your entity in the model editor and in the top menu go to Editor->Create NSManagedObjectSubclass... It will navigate you through the steps. Once you have that, you will have custom class with properties of appropriate type for each entity attribute.

Swift - Saving Int to Core Data only works once

Here's how I'm saving the data
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Theme", inManagedObjectContext: managedContext)
let themeObj = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
themeObj.setValue(num, forKey: "themeNumber")
var error: NSError?
if !managedContext.save(&error)
{
println("Could not save \(error), \(error?.userInfo)")
}
And then loading it
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName:"Theme")
var resultArr = [NSManagedObject]()
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as [NSManagedObject]?
if let results = fetchedResults
{
resultArr = results
}
else
{
println("Could not fetch \(error), \(error!.userInfo)")
}
theme = resultArr[0].valueForKey("themeNumber") as Int
My data model is just the entity Theme with one attribute, themeNumber which is an Integer 16. If I delete the app from the simulator, it loads the correct theme. However, if I change it and run it again... nothing. Any ideas?
You don't need to use setValue. Typically you would do something like this:
themeObj.themeNumber = num
So to fix your problem, you need to actually update the core data object. I just realized that you probably didn't set the themeNumber by the property because you don't have the NSManagedObject subclass setup for your entity. I'll write try to write the fix for how you have it setup.
theme = resultArr[0] as NSManagedObject
theme.setValue(num, forKey: "themeNumber")
if !managedContext.save(&error)
{
println("Could not save \(error), \(error?.userInfo)")
}
After you save it, see if it has the new value that you are looking for.

Resources