Can I insert an object into an NSDictionary? - iphone

I am pulling in a list of coordinates from our web server. I'm storing the whole list as an NSDictionary. While I am using the data (lat, long, radius, name) I would like to update the list of data with 1 or 2 more fields. Is there a way to insert these 2 items to the existing dictionary?
My only existing thought is that I would have to load the data into an NSMutableDictionary to allow additions and just create the new dictionary and overwrite the existing one with the new updated data. Hoping for a simpler or cleaner way rather than ghetto rigging it. Thanks in advance.

From the docs:
The NSDictionary class declares the programmatic interface to objects
that manage immutable associations of keys and values.
So, NSDictionary is immutable--you may not add to it. Using an NSMutableDictionary is not unclean or "ghetto rigging"...this is the whole purpose for an NSMutableDictionary.

Your thought is correct, you have to create an NSMutableDictionary, as the NSDictionary can not be modified.
NSMutableDictionary *newDoc = [[NSMutableDictionary alloc] initWithDictionary:doc];
If you have any immutable arrays or dictionaries in the NSDictionary, you might need a deep copy for modifcations.
NSMutableDictionary *newDoc = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, doc, kCFPropertyListMutableContainers);

Related

iOS Add object in key on NSMutableDictionary (not so simple as that)

How do I add more then one object for the same key? is that possible?
For example, I need to have a dictionary like this:
object:textField.text for key #"Permanent key"
I need to always add objects to that permanent key depending on how many times the user types something on the textfield.
So my dictionary would have lots of entries for the key "permanent key".
This is not possible, keys have to be unique for each value in the dictionary.
If what you need is several objects like this, why not just make an NSMutableArray or NSMutableSet of them? Or have your object be itself an NSMutableArray and you assign it to that key and simply add to this NSMutableArray the new values that are required.
You can Use an NSMutableArray as object, in which you put the objects you want to assign to that unique key.
If you were able to add (say) object A and object B for the same key; Which object would you get when you retrieve with that key? A or B?
Keys must be unique by definition; They are like the numerical indices of an array, but instead of consecutive numbers, they can be arbitrary strings.
As others pointed out, you want to store an array of objects for that key, instead of a single object.

How to model my Core Data entity?

I want to store NoteObjects in Core Data. Normally, a NoteObject has a NSString *mainText and an NSMutableArray *arrayOfTags (an array of NSStrings). I want to now use Core Data, but arrays are a tricky matter with core data. Typically a NoteObject won't have more than 50 tags in its array. So how should I model this? I have two options:
Use a transformable property to store the array
Use a to-many relationship, which I've read is the more "legit" way to do it.
Which one should I use and why? And how would I implement a to-many relationship with my simple structure? I can't seem to wrap my fingers around that concept.
Use to-many relationship. Because it's way better and easier during fetch requests. See the screenshots below. Pay attention to the Relationship manager on the right side, set "To-Many Relationship" from your NoteObject to Tags. Ignore the Player entity.
Oh and pay attention to the "Delete Rule". You might want to delete all the tags associated with a given NoteObject. So set it to Cascade in that case.
NoteObject entity
Tag entity
--Edit:
To add multiple tags you need to first fetch your NoteObject - I assume there will be some sort of ID parameter which you'll use to distinguish NoteObjects. CoreData will automatically generate the add/remove methods for Tags. You'll need to use code similar to the one below:
- (void)addTags:(NSArray *)tags toNoteObjectWithID:(NSString *)noteID {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"NoteObject"];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"noteID == %#", noteID];
[fetchRequest setPredicate:pred];
NoteObject *noteObject = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] lastObject];
for (NSString *tag in tags) {
Tag *t = [NSEntityDescription insertNewObjectForEntityForName:#"Tag"
inManagedObjectContext:[self managedObjectContext]];
t.body = tag;
t.noteObject = noteObject;
[noteObject addTagsObject:t];
}
[self saveContext];
}
You could use a transformable property, but then you need to write the transformer.
If you use a toMany relationship, you have to create an additional entity for tags, which presumably has only one attribute - the string value, and a single relationship. Extrapolating a little, I would guess that you have a finite set of values tags can take on, and you might someday want all notes that have tag X - then you would be able to fetch the entity containing the string value for X and then use that to fetch the NSArray of objects that have X in the relationship (whatever you called it).
Arrays were only tricky in Core Data because they weren't supported prior to iOS 5, so you had to include some attribute (like creation date) by which they could be sorted. If you don't mind requiring iOS 5, you can use ordered relationships. Results are returned in an NSOrderedSet, which is a lot like (and can can be converted to) an array. Or, just re-think the problem -- is the order of the tags on a note important to the note or the user? Would it be okay if you just display the tags in alphabetical order? If so, even better -- just use a plain old (unordered) to-many relationship.

Core Data one-to-many - how do i get objectAtIndex?

I have a class of Entry, and a class of Media. They're both in CoreData, and Entry has a one-to-many relationship with Media. The problem is, Media is an NSSet, and my tableview requires to know the detiails of a Media object at an index. How do i set this relationship up so it's something other than an NSSet, or is there another way to solve this problem?
You choice is NSOrderedSet
If u target deployment more than 10.7 u can mark all relationships as ordered. and get objects by index.
NSSet *entries = // fetch entries
NSArray *array = [NSArray arrayWithArray:[entries allObjects]];
Then you can use objectAtIndex on the array

Editing Core Data row from entity linked to managedObjectContext via relationship

I need to edit a row of data in an Entity that has a relationship with my main Entity from my fetchedResultsController, in this case "theUser" being an instance of my User entity.
I basically need to edit one of the CannedMessage rows that already exist and save it. I can access the "Messages" fine as you see below, but am unsure once I have found the CannedMessage I want as to how I save it back into the managedObjectContext for "theUser"
Any advice?
NSArray *msgs = [theUser.Messages allObjects];
NSPredicate *activeMatch = [NSPredicate predicateWithFormat:#"defaultMessage == 1"];
NSArray *matched = [msgs filteredArrayUsingPredicate:activeMatch];
CannedMessage *msgToEdit;
for(CannedMessage *msg in matched) {
msgToEdit = msg;
}
Your trouble is that your thinking in SQL terms instead of Core Data's object oriented terms. The data you are looking for is not in an SQL row but in the attribute of a managed object. In this case (I assume) you are looking for an attribute of a CannedMessage instance.
The matched array will contain either managed objects initialized with the CannedMessage entity or an instance of a dedicated NSManagedObject subclass (if you setup one which it looks like you did.)
Lets say the attribute is named theMsg. To access the attribute in the generic managed objects:
for(CannedMessage *msg in matched) {
msgToEdit = [msg valueForKey:#"theMsg"];
}
... to access a custom class:
for(CannedMessage *msg in matched) {
msgToEdit = msg.theMsg;
}
It's really important when learning Core Data to simply forget everything you know about SQL. Nothing about SQL truly translates into Core Data. Core Data is not an object-oriented wrapped around SQL. Entities are not tables, relationships are not link tables or joins, attributes are not columns and values are not rows. Instead, Core Data creates objects just like you would if you manually wrote a custom class to model a real world object, event or condition. Core Data uses SQL almost as an after thought as one of its many persistence options.
In my experience, the more you know about SQL, the harder it is to shift gears to Core Data and other object graph APIs. You want to translate the new stuff to what you have already mastered. It is natural but resist the urge.

How should i add Object in NSDictionary for the same key at runtime?

I am trying to add value as array in NSDctionary for the same key, i don't how should i add like that, what i mean in PHP, we have add multi dimension array at runtime like fetching the value form DB like for the same key, we need to add into NSDictonary?
If you have multiple objects associated with a single dictionary key, then you can store those objects in an NSArray, then add an NSArray instance for each key: