NSManagedObject identification number - iphone

Ok, it seems like I'm asking a noob question (maybe I am and I have just been overlooking important details), but I am looking for a "distinguishing" number/attribute about a generic NSManagedObject that I could use as an ID number (I cannot use the name b/c I want to allow the user to create entities with the same names). If this is not existent please explain how I would recreate this. I understand that I could just add an attribute for this and increment a static variable (ex: currentId) but if I do then I have to consider an entity being deleted then how do I logically place the next inserted entity at that index and then return to the last index.

Core Data does not have the notion of an auto-incremented ID field, keep in mind Core Data is an object graph, not a database. It just happens that a datastore could be backed by a database system, a perfect example is SqlLite.
NSManagedObjectId is kind of like a URL with a GUID to be unique. If you want some sort of auto-incremented id you will have to handle this on your own, there are obviously many different ways you might go about this. You could have a separate entity that stores the last id assigned and read it every time you create a new record, increment the value, use that as your new ID and increment the stored value. This would solve your delete problem if you don't want an ID to be re-used. There are obvious concurrency issues here that you may need to solve. Another approach could be to store the ID in a file on the file system, or in NSUserDefaults, just be sure to take account for concurrency and do not accidentally assign the same ID twice.

There is an objectID method for NSManagedObjects, although I do not believe that they are created in any kind of order.
Personally I would just use and ID attribute. What I don't understand is why deleting would cause any problems. The ID would just sit behind the scenes, there wouldn't be any real reason to show it to the user, right?

It seems like you could use a NSNumber identification row on your entities and then simply keep track of how many objects you have (either by keeping a var or fetching the max value from your storage).
Here I found a few examples that might help you achieve your goal.
link

Related

Preventing duplicates in MongoDB using Spring Data (Spring Roo)

I have been trying to get my head wrapped around MongoDB, as it's used by Spring, so I decided to start a little project in Spring Roo.
In my project, I am storing my User Login data to MongoDB. The trouble is that the registration process, which creates a new User object and stores it in the MongoDB, has a tendency to create duplicates despite the fact I have #Unique on the loginId field.
Now, I know part of the problem is that I am thinking about things from a JPA/RDBMS perspective, and MongoDB is not a relational DB and thus has a different set of parameters in which to operate with, but I having trouble finding guidance in anything more than a VERY simple sample code.
First, what Spring/Other annotations are available, and more importantly, commonly used when dealing with MongoDB from a Spring-world? Second, when dealing with documents that need to be "uniqued", how does one typically do this? Do you first search on the unique field to ensure it's not already there first, then do the insert? Third, in JPA-land, I could use the annotations #PrePersist and #PreUpdate to do last-minute data manipulation, like MD5-hashing passwords that have been updated or adding/updating a "Last Modified" date just prior to storing. I know this are JPA-isms, but can I still use those, and if not, is there an alternative for use with Spring Data/MongoDB?
I ended up using the #Id annotation on my Entities, which indicates which field is used as the id field. As long as the field is unique, writting subsequent updates will properly replace the existing entity instead of adding a new one.
I ended up creating additional method to check if there exists a data which have a duplicate value to the one we are entering.
If it exists, i return failure mentioning that there exist duplicate value. Otherwise it saves the newly entered value

iOS find the most common record in core data?

I want to be able to look through all the attributes of an Entity and find the most popular one. I know it has something to do with NSPredicate, but I can't quite wrap my mind around to achieve it.
One possible solution:
Fetch all the entities and loop through it and sort the attributes into different arrays, from there count the items in the arrays to determine the most popular/common one.
Although this might work I'm just wondering if there's an easier or 'cleaner' way of doing it.
Update:
Thanks #Caleb. Let me clarify, I'm looking for a single attribute value that's most often used by instances of a given entity.
That is really a dirty descision.
I would suggest you to make a new entity, say, AttributeCounter, with two attributes - name and count, and every time you add an attribute to a person, change this entity.
But that would only be good descision if you have a few different attributes and lots of persons. If not, here is another approach, that is quite simple:
Get all the enteties with first attribute not nil,count,add to array
Sort it
Here you are

CoreData (IOS) Unique Constraint on Multiple columns?

Is it possible to, in CoreData for an iPhone app, have a Unique Constraint on Multiple columns?
For example:
have Event, EventItems, Items entities
the EventItems entity has a column ORDER
so the ORDER column for an EventItem should be unique for all it's instances relating to the same EVENT
So questions are:
How could I setup this constraint in coredata?
If it's not directly support any suggestions re how to put in place programmatically?
To do
For any core data constraint that operates on more then a single managed object at once you want to look at implementing:
- (BOOL)validateForDelete:(NSError **)error
- (BOOL)validateForInsert:(NSError **)error
- (BOOL)validateForUpdate:(NSError **)error
(I normally have core data make a .h and .m file for the entity, and then make my own category for things like this so I don't have as much work if I change the entity a little later)
If you have something that only needs to make sure values in a single managed object are correct you can use -validate<Key>:error:
To do what you are looking for I would make EventItems' validateForInsert/validateForUpdate
call a common method (maybe validateUniqueOrder). In that method I would use the relationship from EventItems to Event, and then fetch all the EventItems relating to the Event, and then check for uniqueness. I have fairly small sets of relations, so I didn't bother with anything fancy, but if you have a lot of event items associated with given events you might look into NSFetchRequests' setPropertiesToFetch method. Or maybe you can come up with a query that can directly search for duplicated values (I never could, so if you do, reply here to enlighten me).
How could I setup this constraint in coredata?
You control what goes into the data store, so you can impose any constraints you like, no matter how complex. But Core Data is not a database, and it doesn't implement the kinds of automatic constraints that you typically find in a RDBMS.
If it's not directly support any suggestions re how to put in place programmatically?
I'd do a check at the point in your code where you create or modify the affected object. In your case, you could create a custom setter for EventItem's 'order' property that compares the proposed 'order' to that of all the other EventItems related to the same event. Or, you might put the check in Event, and use an appropriate accessor to check any new EventItems as they're added.
Unique Constraints make sure that records in an Entity are unique by the given fields. But unique constraints along with To-Many relationship leads to a lot of weird issues while resolving conflicts.
e.g. “Dangling reference to an invalid object.”
This post is basically focused to a small problem that may take days to fix.
http://muhammadzahidimran.com/2016/12/08/coredata-unique-constraints-and-to-many-relationship/

"On duplicate key update" for core-data

I would like to know if there is some kind of similar functionality or way to preform an "on duplicate key update" function with core-data as there is with MySQL.
What I want to do is to save an object to the database every time a user presses a button. But if the button is already pressed I want to update the row with some new values instead of adding a new row.
The only way I currently know how to do this is to read the rows from the DB, see if the row exists and then update it.. otherwise add a new row. This seems kind of bad to do this way, am I wrong?
The easiest answer to this is to run a query against the Core Data context and get the object back if it exists. This is the most efficient and least error prone solution to the problem.
You do not need to create a separate NSManagedObjectContext and attempt to deal with merge policies, that is a very inefficient and dangerous way to try and resolve such a simple issue.
Core Data handles a lot of caching for you in the background. If you are attempting to retrieve an object that you just created there is a very high probability that it is still sitting in the cache so the response to your query will be nearly instantaneous.
Note
I just went back to both of those sample projects again to file a bug against them and noticed that they have been updated and finally removed the suggestion of creating a new context. They are now using the NSUndoManager where appropriate and a single context.
EDIT
Remember that the core data framework manages persistence of your object graph. It is not an interface to a sqlite database.
Worry about your object life cycle. When do instances get created? When are they destroyed? What makes your instances unique? Using Books as an example entity, a book has an ISBN which is a unique way of identifying a title, yet many copies of each title can exist. You have two choices in your Entity model, you can create separate instances for each copy of the title or have one instance with a count attribute.
The sample projects CoreDataBooks and iPhoneCoreDataRecipes use NSUndoManager to track state changes between views.

iPhone and Core Data: how to retain user-entered data between updates?

Consider an iPhone application that is a catalogue of animals. The application should allow the user to add custom information for each animal -- let's say a rating (on a scale of 1 to 5), as well as some notes they can enter in about the animal. However, the user won't be able to modify the animal data itself. Assume that when the application gets updated, it should be easy for the (static) catalogue part to change, but we'd like the (dynamic) custom user information part to be retained between updates, so the user doesn't lose any of their custom information.
We'd probably want to use Core Data to build this app. Let's also say that we have a previous process already in place to read in animal data to pre-populate the backing (SQLite) store that Core Data uses. We can embed this database file into the application bundle itself, since it doesn't get modified. When a user downloads an update to the application, the new version will include the latest (static) animal catalogue database, so we don't ever have to worry about it being out of date.
But, now the tricky part: how do we store the (dynamic) user custom data in a sound manner?
My first thought is that the (dynamic) database should be stored in the Documents directory for the app, so application updates don't clobber the existing data. Am I correct?
My second thought is that since the (dynamic) user custom data database is not in the same store as the (static) animal catalogue, we can't naively make a relationship between the Rating and the Notes entities (in one database) and the Animal entity (in the other database). In this case, I would imagine one solution would be to have an "animalName" string property in the Rating/Notes entity, and match it up at runtime. Is this the best way to do it, or is there a way to "sync" two different databases in Core Data?
Here's basically how I ended up solving this.
While Amorya's and MHarrison's answers were valid, they had one assumption: that once created, not only the tables but each row in each table would always be the same.
The problem is that my process to pre-populate the "Animals" database, using existing data (that is updated periodically), creates a new database file each time. In other words, I can't rely on creating a relationship between the (static) Animal entity and a (dynamic) Rating entity in Core Data, since that entity may not exist the next time I regenerate the application. Why not? Because I have no control how Core Data is storing that relationship behind the scenes. Since it's an SQLite backing store, it's likely that it's using a table with foreign key relations. But when you regenerate the database, you can't assume anything about what values each row gets for a key. The primary key for Lion may be different the second time around, if I've added a Lemur to the list.
The only way to avoid this problem would require pre-populating the database only once, and then manually updating rows each time there's an update. However, that kind of process isn't really possible in my case.
So, what's the solution? Well, since I can't rely on the foreign key relations that Core Data makes, I have to make up my own. What I do is introduce an intermediate step in my database generation process: instead of taking my raw data (which happens to be UTF-8 text but is actually MS Word files) and creating the SQLite database with Core Data directly, I introduce an intermediary step: I convert the .txt to .xml. Why XML? Well, not because it's a silver bullet, but simply because it's a data format I can parse very easily. So what does this XML file have different? A hash value that I generate for each Animal, using MD5, that I'll assume is unique. What is the hash value for? Well, now I can create two databases: one for the "static" Animal data (for which I have a process already), and one for the "dynamic" Ratings database, which the iPhone app creates and which lives in the application's Documents directory. For each Rating, I create a pseudo-relationship with the Animal by saving the Animal entity's hash value. So every time the user brings up an Animal detail view on the iPhone, I query the "dynamic" database to find if a Rating entity exists that matches the Animal.md5Hash value.
Since I'm saving this intermediate XML data file, the next time there's an update, I can diff it against the last XML file I used to see what's changed. Now, if the name of an animal was changed -- let's say a typo was corrected -- I revert the hash value for that Animal in situ. This means that even if an Animal name is changed, I'll still be able to find a matching Rating, if it exists, in the "dynamic" database.
This solution has another nice side effect: I don't need to handle any migration issues. The "static" Animal database that ships with the app can stay embedded as an app resource. It can change all it wants. The "dynamic" Ratings database may need migration at some point, if I modify its data model to add more entities, but in effect the two data models stay totally independent.
The way I'm doing this is: ship a database of the static stuff as part of your app bundle. On app launch, check if there is a database file in Documents. If not, copy the one from the app bundle to Documents. Then open the database from Documents: this is the only one you read from and edit.
When an upgrade has happened, the new static content will need to be merged with the user's editable database. Each static item (Animal, in your case) has a field called factoryID, which is a unique identifier. On the first launch after an update, load the database from the app bundle, and iterate through each Animal. For each one, find the appropriate record in the working database, and update any fields as necessary.
There may be a quicker solution, but since the upgrade process doesn't happen too often then the time taken shouldn't be too problematic.
Storing your SQLite database in the Documents directory (NSDocumentDirectory) is certainly the way to go.
In general, you should avoid application changes that modify or delete SQL tables as much as possible (adding is ok). However, when you absolutely have to make a change in an update, something like what Amorya said would work - open up the old DB, import whatever you need into the new DB, and delete the old one.
Since it sounds like you want a static database with an "Animal" table that can't be modified, then simply replacing this table with upgrades shouldn't be an issue - as long as the ID of the entries doesn't change. The way you should store user data about animals is to create a relation with a foreign key to an animal ID for each entry the user creates. This is what you would need to migrate when an upgrade changes it.