Getting types from NSManagedObject - ios

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.

Related

Value of type 'AppDelegate' has no member 'managedObjectContext'

func saveName(name: String){
//1
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let person = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
//3
person.setValue(name, forKey: "name")
//4
var error: NSError?
if !managedContext.save(&error) {
print("Could not save \(error!), \(String(describing: error?.userInfo))");
}
//5
people.append(person)
}
I can't get this program working correctly. I was trying save to CoreData.
In Swift 3, you access the context object like this:-
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
As the managed object context is used frequently add a lazy instantiated property in AppDelegate
lazy var managedObjectContext : NSManagedObjectContext = {
return self.persistentContainer.viewContext
}()
Both entity and managedObjectContext are supposed to be non-optional.
Change your second line in your code to access the managed object context
let managedContext = appDelegate.persistantContainer.Viewcontext

batch request for single objectID swift

I'm trying to update single entity in swift with help of batch request. It works perfect to update all the entities. Is it possible to update single entity using it's objectID?
Here is the example code:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let batchRequest = NSBatchUpdateRequest(entityName: "Outlays")
batchRequest.propertiesToUpdate = ["purchase": self.purchase.text!]
batchRequest.resultType = .UpdatedObjectsCountResultType
do {
let results = try managedContext.executeRequest(batchRequest) as! NSBatchUpdateResult
print(" \(results.result) results changed")
} catch {
print(error)
}
Thanks in advance!
No, there is not need updating a single entity (NSManagedObject) in a batch request.
The easiest way is just to set the new value on your Outlays objects. Of course they have to be of type NSManagedObject. Call saveContext on your NSManagedObjectContext afterwards:
myOutlay.text = "changed"
let managedContext = appDelegate.managedObjectContext
var error: NSError? = nil
managedContext.save(&error)
If you only have the NSManagedObjectID of your NSManagedObject, it's required to get it from the Datastore first:
let managedContext = appDelegate.managedObjectContext
var myOutlay: Outlays = managedObjectContext.existingObjectWithID(outlayManagedID, error: nil) as? Outlays
myOutlay.text = "changed"
let managedContext = appDelegate.managedObjectContext
var error: NSError? = nil
managedContext.save(&error)

cant get the integer from core data atribute

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.

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.

iOS core data faults outnumber entities after fetch

I'm building an app that stores locations in core data when the server connection is no longer available, then pushes these locations to the server when a connection is restored.
After fetching and printing these fetched objects from core data, I get tons of faults initially. I understand faults and what they represent, but shouldn't the number of faults be the same number of objects? The number of faults heavily outnumbers the number of objects (I can print out a 100+ faults for only 10 Location entity array objects of {longitude, latitude, timestamp}).
I was hoping someone could advise me on what I'm doing wrong or if this is usual behavior. Much appreciated.
AppDelegate.swift
calls fetch and prints core data objects when server returns to connected
var fetchedCoreData = self.coreDataManagement.fetchLog()
for dataPoints in fetchedCoreData
{
println(dataPoints)
}
`CoreDataManager.swift handles storing/fetching core data of Location entity
var locations = [NSManagedObject]()
//coordinates passed from AppDelegate
func saveCoords(latCoord: String, longCoord: String, timeCoord: String) {
let appDelegate =
UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Location",
inManagedObjectContext:
managedContext)
let coordsInfo = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
coordsInfo.setValue(latCoord, forKey: "latitude")
coordsInfo.setValue(longCoord, forKey: "longitude")
coordsInfo.setValue(timeCoord, forKey: "timestamp")
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
locations.append(coordsInfo)
}
`
//fetch core data objects
func fetchLog() -> Array<AnyObject> {
let appDelegate =
UIApplication.sharedApplication().delegate as AppDelegate
let fetchRequest = NSFetchRequest(entityName: "Location")
fetchRequest.returnsObjectsAsFaults = false;
var fetchResults = appDelegate.managedObjectContext!.executeFetchRequest(fetchRequest, error: nil)
return fetchResults! as Array<AnyObject>
}
`

Resources