How can a user add a new field to a table by creating a new attribute - ios

I'm new to Core Data and I got stuck at this part of my xCode project.
I have created a core data entity "Person" and this entity has the following attributes:
name;
age;
birthday;
address;
and this attributes are getting displayed in a tableview. So far so good.
My problem is that I want the table to have an "Add Field" or "Add Row" cell so when the user wants to add more information in addition to these already created attributes he just clicks the cell and chooses the field name and type.
For example if he wants the person's "phone number" in the detail view of the table he names the new field "phone number" and chooses its type "number". Then he has an extra field where he can add the person's phone number.
How can I do this in core data? Is there a way for a user to manually add a new attribute to an entity and choosing its format? What is the best approach? Thanks.

You can't do exactly what you want with Core Data. Core Data can't change structure except if you make a new version of your design, but you do that in xcode.
But you can easily add another table called f.ex. information, which links to the person single connection and has the person linking back many to the information table.
This way, you can add as many fields and values as you want, of course all the extra fields you add would follow the same person, so if you want to use cellPhone field, you must add that to all.
I would recommend that you use direct SQL, and don't use Core Data. Core Data is not a database, it is an object store, and when you get better at iOS development, you will understand the difference, it is much bigger than you might think at first.
There is an excellent high level library for SQLite, called FMDB, you can find it on github here : https://github.com/ccgus/fmdb
Here you can do direct SQL queries like "Alter Table" and more on the fly, though what you are after isn't very simple, it could be real fun project to do.
Good luck with this.

I don't think this is directly possible in Core Data because its purpose is object persistence and you can't add new properties to objects dynamically. It could be faked to some degree using a to-many relationship to an "extra property" entity that had name, value (as string), and data type fields.
I believe your best option would be using SQLite in order to modify the table structure on the fly. (http://www.sqlite.org/lang_altertable.html)

My last company did something like this, but its not trivial. I don't have access to the code so this is more or less going to be from memory.
you provide transformable property in your entity (which will be a dictionary)
the model object has to provide the getter and setter for this that in turn drive the primitive methods to set/get an attribute
you provide a getter/setter along the lines of -objectForKey and -setObject forKey, which read and write values
when you are told to 'fault', you update the dictionary in the entity
In summary, maintain a dictionary of key value pairs. Perhaps you maintain a shadow dictionary that gets initialized and updated as needed. Its been around 4 years since I last saw this code so a little fuzzy on it. But you should get the idea. It was like magic - you can arbitrarily set any key/value pair (assuming string keys and NSCoding compliant values), and can always ask for the keys by asking the dictionary for its current set of keys.

Related

Remove or Add an attribute to CoreData at runtime programmatically

I have to create and remove attributes based on an api response in Objective C.
For example, Now my api response contains fields "facebook", "whatsapp" and "viber". But in future the reponse can add "youtube". Based on this response, I have to remove all the attributes and values of an entity "Social", and create Four attributes now and set values.
How to do that programmatically? Because the default *.xcdatamodeld file cant help me here, right?
Note: My project is in objective C.
The data model is mutable when the app starts-- you can completely build the model in code, and not use the model editor, for example. But as soon as you load a persistent store file, you must treat the model as fixed. Any changes after loading a persistent store will cause crashes. That means any changes would have to happen before calling either loadPersistentStores(completionHandler:) or addPersistentStore(with:completionHandler:).
Alexander's suggestion of optional attributes is a good one. If you need the model to be more dynamic, you would need to create a new related entity which would store the service name plus whatever information you need to save about the service. If you did this, your Social entity would have a to-many relationship to a new entity called something like Service. Service would have a string property called name that would have values like twitter, facebook, youtube, etc. It would also have whatever other attributes you need to save about the service.
You can create all 4 fields in advance and just make them optional and fill them depending on the server response. But you cannot add new attributes in runtime. Your *.xcdatamodeld file compiles into *.momd and it contains all the data to create tables in the DB since Core Data by default works with SQLite under the hood and it's a relational database management system.
To make attributes optional you should check that.
And then newly created objects contain nil as default values of object properties. So, in your case your "youtube" property of Social object will be just nil.

CoreData mark one record as favourite (mutually exclusive)

Overview:
I have an iOS app that uses CoreData
There is an entity called Animal
It has a set of records Lion, Tiger and Elephant
I would like to mark only one of the records as favourite.
Similar entities with the same approach:
Similarly I could have other entities such as Car, Bike.
Each entity would have a set of records.
Again each entity should only have one favourite record
Reason:
App has an option to create a new document
When the new document is created, it would be populated with default values for each entity (by selecting the favourite record of each entity)
Note: Only one record can be marked as favourite at a given time
Possible models I thought of:
1. Field called isFavourite
Create a field in Animal called isFavourite.
Mark only one of the rows as isFavourite as true.
Much of the logic to maintain isFavourite is managed in code.
2. Separate entity called Favourite
Create a separate table called Favourite and have a dummy row in it.
Establish a relationship from Favourite to Animal called animal.
This will point to the favourite record.
Questions:
What is the preferred approach to tackle this problem ?
Are there any other alternatives ?
Go with option 2, maybe call it Config. If you want to ensure it is just a singleton add a attribute that is unique and can only be zero.
You can write a helper computed var returning true if the reverse relationship is non-nil.
Main advantage of option 2 is the simplicity of changing the favourite, you don't have to scan through all the items to to set them non-favourite just change it on the singleton config.
Give some thought to other parts of the app and to what you might want to do in the future.
Adding a field: Works OK but requires some code to maintain, which might be error prone. On the other hand maybe one day the app might allow multiple favorites, and this will just work with that.
Using a separate entity: Also works OK but adds a whole new entity where you'll only have a single instance. In general, if you have an entity where you only ever want one instance, you're doing it wrong. On the other hand this also works well with the potential for multiple favorites.
A third approach is to save the objectID for the favorite animal somewhere outside of Core Data, like UserDefaults. Save it, and then find the favorite by using NSManagedObjectContext's existingObject(with:) method. You can't save the NSManagedObjectID directly but you can get its uriRepresentation() and save that.
I'd probably go with #1 in most cases but it depends what else I need in the app.

How to add same object type as different tables in same realm?

I'm using realm to cache certain network data coming down which is specific to the last search. I'd also like to be able to star or pin this data to save it for future usage. The data objects are exactly the same and I can't find anything in the documentation that allows me to save them in separate tables in Realm.
The easiest way to go about doing this would be to simply create a subclass of your model object with a different name (e.g., MyDataObject and its subclass MySavedDataObject). This will create a new table in the Realm database file with the same schema and will let you distinguish between the two types of objects.
You can then create a copy of a normal object as a saved object as simply as the following:
let myNewSavedObject = MySavedDataObject(value: myDataObject)
That all being said, instead of duplicating data, I would personally recommend being a bit more efficient with the existing data set. Surely simply adding an additional boolean property to the schema named something like saved would let you simply mark objects that you wish to keep without needing a whole second table. :)

Core Data: Which record loads by default in core data if you do not specify which one?

I have a static table for settings where I want to pull some stuff from an entity in Core Data. The use case does not lend itself to a table of records as you usually see. Rather each row of the static table is really a field related to the user--as in a user profile. I have a feeling that in testing I may have created more than one record in the entity. I know there are programs that let you see the SQL lite database underneath, but my question assumes you do not have this tool and are relying just on Xcode.
My question is when you have more than one record in a Core Data entity/table, and you try to load data from the managed object context into a VC, one field into one element, what record is shown by default?
Related to this, if you don't know how many managed object or rows are in the database, is there anyway to specify which record you want since there are no auto ids as you would use in a traditional database?
The record that gets loaded from the fetch first. Depending on your sort that might be consistent or it might be random.

tableview from multiple core data entities swift

I am struggling with something I think should be basic but cannot figure out. I have two entities in core data with a one to one and one to many relationship. They are Company which can have multiple Opportunities.I want to load a table view listing the opportunities (sorted by name) with their associated companies. Can this be done by simply accessing the Opportunity entity? If so, how do I access company? The Opportunity class references it as a "Company" type and so I tried to go using dot notation through to company.companyName but it failed on that, and if I change it to simply company (of type Company) it does show .Company: and other reference data but not the simple name field I am looking for. This seems as if it should be simple but...........
This was simple and I was overlooking the ability to load the fetchedresultscontroller with the right type (in my case the Opportunity class) and then use dot notation from there. I was trying to do it with key value access which did not work. Cheers

Resources