How to add two items at a specific index in an entity in CoreData in Swift - swift

I am moving rows inside a collectionView, I have no sorting on the data so all new cells are inserted at the end of the table, but when I move a cell I want to specifically select the index where it should be moved inside the entity in core data, this way the collectionView will automatically display the moved cell at the updated row without any additional work, is that possible without creating an additional ID attribute?
The entity is named List and it has two attributes, task_name and task_bool.
var myData:[NSManagedObject] = []
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let newItem: AnyObject = NSEntityDescription.insertNewObjectForEntityForName("List",
inManagedObjectContext:
managedContext)
var deleltedRow = myArray[indexPath.row].valueForKey("task_name") as! String
myData.removeAtIndex(indexPath.row)
newItem.setValue(deleltedRow, forKey: "task_name"); // how would I add atIndex: here??
newItem.setValue(true, forKey: "task_bool"); // how would I add atIndex: here??

Core data maintains an unordered collection of objects. If you want to display those objects in a specific order then you need to sort them, either while fetching or afterwards. That means that the objects need to have some information inside them on which you can sort. You don't have anything currently so you'd need to add an order type attribute and maintain it with appropriate values.

Core Data does not store objects in an ordered manner. If you want to display these objects in a specific order, you will need a property/attribute in your entity which lets you order the list the way you want.
It might be a good idea to add a order attribute to the entity and use that for the ordering.

Related

How can I bulk set the value of some results, while limiting how many I update?

In the code below, I like the simplicity of calling
results.setValue, rather than iterating over an array and calling it a bunch of times.
It seems likely that there is some way to do this without iterating over an array, but I guess really my concern is that it appears to be significantly slower to iterate. In my testing, for 500 results, it took just under 3 milliseconds to update them in bulk, vs. 537 milliseconds to iterate.
Seems like there has got to be a built in way to set the value for a subset of the results. Limiting the results by a count doesn't appear to be supported, due to the lazy nature, but I don't see any simple way to update them in bulk. I could order them by a unique field, and get the 500th and then filter I suppose to get a new result set, but seems like there should be a better way to do it.
var results = realm.objects(CloudUpdate.self).filter("status = %#", "queued")
let limitedResults = updates[0..<500]
try! realm.write {
// this works, except it sets all the results to posted
// results.setValue("posted", forKey: "status")
// I'd like to be able to do
// limitedResults.setValue("posted", forKey: "status")
// or something rather than iterate as below
// -- note that limitedResults gets smaller as we set them
// because of the filter on the results.
while limitedResults.count > 0 {
limitedResults[0].setValue("posted", forKey: "status")
}
}
Realm can do that update using key paths of the object, and the performance over large datasets is very good.
The use case is not clear but if you have a dataset and want to update the first X number of objects, this will do it
Given a person class with a name property
class PersonClass: Object {
#Persisted var name = ""
}
and you want to update the first three names to... "Jay"
let peopleResults = realm.objects(PersonClass.self)
let peopleList = RealmSwift.List<PersonClass>()
peopleList.append(objectsIn: peopleResults[0...2]) //see note
try! realm.write {
peopleList.setValue("Jay", forKey: "name")
}
Keep in mind though, as soon as realm objects are manipulated by high level Swift functions, the performance will degrade and more importantly, those objects are no longer lazily loaded - they are all loaded into memory and could potentially overwhelm the device.
One other thing to note is that Realm has no pre-defined ordering so ensure the results have a .sorted(byKeyPath: if you want to update objects by an order.

CoreData object is fetched in the correct order, but nested objects are un-ordered

I have the following code to fetch Person object from CoreData model:
let fr:NSFetchRequest<Person> = Person.fetchRequest()
let sd = NSSortDescriptor(key: "name", ascending: false)
fr.sortDescriptors = [sd]
let persons = try? dataController.context.fetch(fr)
This works fine, and I get an array of [Person] in the right order (by name).
let children = persons[0].children // children set is in random order
However, each person has multiple Child objects. These are fetched automatically with each Person, however, these Child objects are not sorted. They come in random order.
How can I control the order in which these Child objects are fetched?
Edit: I am aware that I can order the nested objects manually after being fetched from CoreData, but I am reluctant to do that since that would not be efficient and would cause faulting on all child objects. I am looking for a way that lets CoreData fetch the child objects in a certain order.

How to find array value of a data model in a view container of specific row of that array that user typed?

I don't know how to find array value of that particular index which user has typed. I had connected that array to my data model which contain 2 values ?
I have tried .contain value after implementing a new variable of the data model but it hasn't worked
let productsNamess = document.data()["ProductName"] as! String
let quantityGame = document.data()["Quantity"] as! String
// making a new net stock data incoming class
let newClassForProducts = dataModelOutgoing()
newClassForProducts.productName = productsNamess
newClassForProducts.quantity = Int(quantityGame)
// forward data to main dataincoming main class
self.dataIncoming.append(newClassForProducts)
I dont know how to take data out of an array which contains two values in one array.

xcode swift 4 Core Data relation between entities?

i am trying to make relation entity between 2 entities , unfortunately its not working well since i am still new with swift.
for example i have playlist table and songs table i want to make relation between them ?
and this is the Fetch Request :
let fetchRequest = NSFetchRequest(entityName: "Playlist")
// // Add Sort Descriptor
// let sortDescriptor = NSSortDescriptor(key: "playlist_name", ascending: true)
// fetchRequest.sortDescriptors = [sortDescriptor]
let context = Appdelegate().managedObjectContext
// Execute Fetch Request
do {
let result = try context.executeFetchRequest(fetchRequest)
print(result)
} catch {
let fetchError = error as NSError
print(fetchError)
}
can i create third table to make relation between songs and playlists like this ?
You need to create the relationship in the Core Data model editor. It's easier to use the model editor if you switch it to table mode using this control at the bottom of the window:
When you do that, the main part of the window will look something like this:
Click the "+" button in the relationships section to add a relationship. Fill in the destination entity and be sure to create an inverse relationship.
You should not create a third table to create the relationship. That's something you do in SQL but not in Core Data in most cases.
You may also want to review the relationships section of Apple's Core Data Programming Guide

Retrieving NSOrderedSet from Core Data and casting it to entity managedObjectSubclasss

Im making a Fitness app to learn Core data, and I have found that I need to let the user store every performed workout as a WorkoutLog item, and in there, there should be a series of ExerciseLogs which represents performances of that exercise (it contains each lift and also a reference to the actual exercise design).
Problem is that after a while i realize that i need to have these ordered, so that the next time i want to show the user their workout, the order that the exercisese were performed should be the same.
So I checked "ordered" in the top right of the image there, and now my code is in dire need of an update. I have tried to read as much as I could about working with NSOrderedSet and how to fetch them from core data and then manipulate them, but I havent really found much of use to me. (I have no experice in objective-c)
For example my code that used to be:
static func deleteWorkoutLog(_ workoutLogToDelete: WorkoutLog) {
guard let exerciseLogsToDelete = workoutLogToDelete.loggedExercises as? Set<ExerciseLog> else {
print("error unwrapping logged exercises in deleteWorkoutLog")
return
}
I get the error: .../DatabaseFacade.swift:84:77: Cast from 'NSOrderedSet?' to unrelated type 'Set' always fails
So what ive learned about sets and core data no longer seems applicable.
Im far from an expert in programming, but im very eager to learn how to get access to the loggedExercises instances.
TLDR; Is there a way to cast NSOrderedSet to something I can work with? How do we usually work with NSManagedSets from core data? Do we cast them to Arrays or MutableSets? I would very much appreciate an example or two on how to get started with retrieving and using these ordered sets!
Thanks
For anyone else wondering how to get started with orderedSets in core data:
After setting my the WorkoutLog.loggedExercises "to-many" relationship to be ordered, I managed to access them through the mutableOrderedSetValue function like this:
static func deleteWorkoutLog(_ workoutLogToDelete: WorkoutLog) {
let orderedExerciseLogs: NSMutableOrderedSet = workoutLogToDelete.mutableOrderedSetValue(forKey: "loggedExercises")
let exerciseLogsToDelete = orderedExerciseLogs.array
for exerciseLog in exerciseLogsToDelete {
guard let exerciseLog = exerciseLog as? ExerciseLog else {
return
}
Works great so far.
And to rearrange the NSOrderedSet I ended up doing something like this:
// Swap the order of the orderedSet
if let orderedExerciseLogs: NSOrderedSet = dataSourceWorkoutLog.loggedExercises {
var exerciseLogsAsArray = orderedExerciseLogs.array as! [ExerciseLog]
let temp = exerciseLogsAsArray[indexA]
exerciseLogsAsArray[indexA] = exerciseLogsAsArray[indexB]
exerciseLogsAsArray[indexB] = temp
let exerciseLogsAsOrderedeSet = NSOrderedSet(array: exerciseLogsAsArray)
dataSourceWorkoutLog.loggedExercises = exerciseLogsAsOrderedeSet
}