Obtaining an array of objects from fetch request - ios

I have an object called Projects that I save to core data. I then add multiple projects to core data. I want to retrieve those objects as an array from core data. The following code gets this error:
-[NSAsynchronousFetchResult mutableCopyWithZone:]: unrecognized selector sent to instance
var uploadPhotos : NSMutableArray? = []
var activeProject : String!
override func viewDidLoad() {
super.viewDidLoad()
projectPicker.dataSource = self
projectPicker.delegate = self
isInSegmentPhoto = true
//let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Project")
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Project.fetchRequest()
let entityDescription = NSEntityDescription.entity(forEntityName: "Project", in: sharedDelegate.managedObjectContext)
fetchRequest.entity = entityDescription
do {
let result = try self.sharedDelegate.managedObjectContext.execute(fetchRequest)
print(result)
projects = result.mutableCopy() as! [Project]
} catch {
let fetchError = error as NSError
print(fetchError)
}
}
When I run the program it prints out the list of projects, but crashes on the first line of the do-catch.

Please, please use Swift native types, NSMutableArray has no type information.
var projects = [Project]()
...
projects = try defaultManagedObjectContext().fetch(fetchRequest) as! [Project]
Since the fetch request is clearly a Project request you can safely unwrap the result.
mutableCopy() causes the error, because NSFetchRequestResult(the umbrella protocol of all possible result types) does not respond to that method.

Figured it out! I was using the wrong method. Replace execute with fetch.
self.sharedDelegate.managedObjectContext.fetch(fetchRequest)

Related

Getting specific attributes from coredata swift

I have a request for an entity in core data:
override func viewWillAppear(animated: Bool) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Constants")
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Within the entity Constants there are 4 attributes: moneyPerSecondSave,moneySave,tapMultiplierSaveandtapValueSave.
My question is, is there a way that after I have got the results can I make four variables which each hold each of the values of the attributes.
I have already tried using valueForKey:
moneyConstants.money = results.valueForKey("moneySave")
However when I try this it pulls up an error: `Value of type '[AnyObject]' has no member 'valueForKey'. Any help would be appreciated.
'results' is an array which holds 'Any' type. You can cast it to an array with the type you expect and get the rest of the data like this:
if let constants = results as? [Constants] {
let moneyPerSecond = constants[0].moneyPerSecondSave
print("moneyPerSecond: \(moneyPerSecond)")
}
You can also use valueForKey of course, like this:
if let match = results[0] as? Constants {
let money = match.value(forKey: "moneySave") as! Float
print("money: \(money)")
}
You can use propertiesToFetch & resultType attribute of NSFetchRequest to retrieve only specific property values of Constants.
You can take inspiration from https://stackoverflow.com/a/6267875/3339346

Swift: CoreData call to specific object ID

I'm discovering new concepts as a fresh developer, I have been trying to understand core data, and run into an issue with a tutorial I've been walking through. I am getting an error when I call an item using the Object ID. The error is - Type 'Person.Type' has no subscript members. it may be because I am just not doing it correctly, or some other reason. I'm sure someone can shine some light on the subject
Here is a function I wrote to get a specific item out of the Data Stack,
func getObjectById(id: NSManagedObjectID) -> Person?{
return context.objectWithID(id) as? Person
}
Here is how I am calling the function
func callFirstObject(){
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let personService = PersonService(context: context)
let firstPerson = personService.getObjectById(Person[0].objectID!)
}
and from there I am just calling callFirstObject() inside a button.
Edit: I have a function to call all of my objects
func getAllObjects() -> [Person]{
return getObject(withPredicate: NSPredicate(value: true))
}
and a function to call all of my objects with a predicate
func getObject(withPredicate queryPredicate: NSPredicate) -> [Person]{
let fetchRequest = NSFetchRequest(entityName: Person.entityName)
fetchRequest.predicate = queryPredicate
do {
let response = try context.executeFetchRequest(fetchRequest)
print("\(response)")
return response as! [Person]
} catch let error as NSError {
// In case of failure
print("There was an error - \(error)")
return [Person]()
}
}
I am just trying to call a specific name in the stack.
If more information is needed, I am glad to provide.
Person has no subscript members because Person is the class name. The subscript, [0], should be called on an array of Person objects.
That could look something like this:
func callFirstObject(){
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let personService = PersonService(context: context)
// Person Array
let persons: [Person] = [person1, person2, person3 ]
let firstPerson = personService.getObjectById(persons[0].objectID!)
}
Edit: I'm kind of confused the logic though. If you have the person already, you have to in order to access the objectID, then I don't see why you need to fetch it again. Can we see some more context around these two methods?
Answering your question from the comment below:
If you want to get all of the records for the Person model you can do as follows:
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Person")
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
people = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error)")
}
This will give you all of the Person objects stored in Core Data

Getting both attribute name and value when reading from core data

I need to get both the attribute name and the value for the attribute when I'm reading from my core data, is there any easy way of doing this?
I've been trying to retrieve the first element in my object model as a Dictionary, but that gives me an error saying:
fatal error: NSArray element failed to match the Swift Array Element
type
My code looks like this:
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let fetchReq = NSFetchRequest(entityName: "ActiveIndexes")
fetchReq.resultType = NSFetchRequestResultType.DictionaryResultType
receivedList = context.executeFetchRequest(fetchReq, error: nil) as! [ActiveIndexes]
println(receivedList[0])
Any suggestions would be appreciated.
NSManagedObjects have a rich API for introspection.
let activeIndex = retrievedList[0]
for (key, value) in activeIndex.entity.attributesByName {
println("\(key) : \(activeIndex.valueForKey(key as NSString))")
}

How to access to entity field by attribute name in core data

I have entity with attribute id.
I seen example:
var appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
var context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "myentity")
request.returnsObjectsAsFaults = false
if let results = context.executeFetchRequest(request, error: nil) {
if results.count > 0 {
for result: AnyObject in results {
println(result.id)
}
}
But for me it return error:'AnyObject' does not have a member named 'id'
How can I do it in last version Xcode in swift?
Make an NSManagedObject Subclass. Once you have done this you can access the attributes using dot syntax rather than using object for key. Apple's documentation on NSManagedObject can be found here and information about creating the subclass here. Then in your for loop you cast the object as your managed object subclass type.
var error: NSErrorPointer = nil
if !fetchedResultController.performFetch(error)
{
println("Unresolved error: \(error), \(error.debugDescription)")
}
let results = fetchedResultController.fetchedObjects as [YourSubclass]
for result in results {
println(result.id)
}

Core Data: How do I delete all objects with an attribute in Swift?

Say for simplicity that I have an entity named DOWJONES. There are two attributes for every object ex AAPL and AAPL_NSDate. ValueForKey:AAPL returns the stock price history and ValueforKey AAPL_NSDate the corresponding date.
How can I delete the stockprice history and corresponding date quickly and efficiently in swift?
This is how I query:
var appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!
var request = NSFetchRequest(entityName: "DOWJONES")
request.returnsObjectsAsFaults = false
var dowjones = context.executeFetchRequest(request, error: nil)! as [DOWJONES]
var aapl = (dowjones as NSArray).valueForKey("AAPL") as NSArray
As suggested from #chris-wagner this is how I could iterate over the results and delete.
func deleteCoreDataObjects(){
var request = NSFetchRequest(entityName: "DOWJONES")
request.returnsObjectsAsFaults = false
var dowjones = context.executeFetchRequest(request, error: nil)!
if dowjones.count > 0 {
for result: AnyObject in dowjones{
context.deleteObject(result as NSManagedObject)
println("NSManagedObject has been Deleted")
}
context.save(nil)
}
}
You can do batch requests directly onto the data store as of iOS 8, using NSPersistentStoreCoordinator's executeRequest(_ request: NSPersistentStoreRequest, withContext context: NSManagedObjectContext, error error: NSErrorPointer) method.
You create the persistent store request similarly to a fetch request, then pass it to the PSC using the above method.
Note however that you shouldn't have any in-context references to objects you're deleting with this method.
There's a nice explanation of it here.
Iterate over the results from your fetch request and call self.context.deleteObject(_:) on each one.

Resources