Keeping a specific Order of an NSMutableDictionary Object - ios

I am trying to write a method which will allow me to keep the order of my NSMutableDictionary keys when they are being inserted into the data structure. I know that the NSMutableDictionary works of a hash map, hence not maintaining specific order.
So I need to somehow keep track of the keys which are being inserted into the dictionary, and when retrieving the values from the dictionary, the keys are to be printed(key values) in this same order as when originally inserted. The keys which are inserted into the dictionary are alphanumeric. They just need to be printed out in the same order as when inserted into the NSMutableDictionary.
Can this be achieved? I would like to remain using the NSDictionary Data Structure.

NSDictionary (and all its relations) are unordered collections so to "keep its order" makes no sense as there is no order.
If you are wanting to retrieve objects in a specific order then you need to be using an NSArray. (Or NSOrderedSet if uniqueness of hashes is important).
Simple and naive option
If you have a dictionary structure of...
{
key1:value1,
key2:value2,
key3:value3,
//and so on
}
Then you might be better using something like...
[
{
key1:value1
},
{
key2:value2
},
{
key3:value3
}
]
// i.e. an array of dictionaries
More code but much better option
Or you could create a new collection class as a subclass of NSObject.
In the class you could have something like...
- (void)addObject:(id)object forKey:(id)key
{
self.dictionary[key] = object;
[self.array addObject:key];
}
And...
- (id)objectForKey:(key
{
return self.dictionary[key];
}
And...
- (id)objectAtIndex:(NSUInteger)index
{
return self.dictionary[self.array[index]];
}
And even...
- (void)removeObjectForKey:(id)key
{
[self.dictionary removeObjectForKey:key];
[self.array removeObject:key];
}
You could even make it conform to fast enumeration so you can do...
for (id object in mySuperSpecialCollection) {
}
and make it dispense objects in the order of the array.

Can this be achieved? I would like to remain using the NSDictionary Data Structure.
No. When using instances of NSDictionary the actual class is private. As often with class clusters, it's not possible to subclass NSDictionary and use derived functionality (storing key value pairs).
The best way to go is to set up your own data structure, maybe using an NSOrderedSet and an NSDictionary in conjunction.

Related

how to parse a dictionary inside an array, which is in a dictionary

In my JSON response i receive a dictionary, which has a array, inside that array is a dictionary with few key-values, to make it simple to understand here is the JSON response:
{
weather = (
{
description = haze;
icon = 50n;
id = 721;
main = Haze;
}
);
}
I want to know how can i retrieve the elements description, icon, id and main. Suppose i have a NSString called str, how can i add the value of description to this string. I have tried many different things, but none seem to work. The one i thought should work, but didn't is:
str = [[[dir valueForKey:#"weather"] objectAtIndex:0] valueForKey:#"description"];
Can someone let me know how can i access those 4 values. I don't want to create a new array of those values and then retrieve them. Regards.
Use NSJSONSerialization to convert your JSON data to NSObjects.
Then you need to index into your objects based on their structure.
If the structure is fixed, and guaranteed, you can do it with fixed indexes/keys:
//data in theJSONDict.
NSArray *outerArray = theJSONDict[#"weather"];
NSDictionary *firstWeatherItem = outerArray[0];
NSString *firstItemDesc = firstWeatherItem[#"description"];
You could also do it all in 1 line:
firstItemDesc = theJSONDict[#"weather"][0][#"description"];
But that is much harder to debug.
If this is JSON data coming from a server you need to code more defensively than above, and write code that tries to fetch keys from dictionaries, tests for nil, and either loops through the array(s) using the count of objects, or tests the length of the array before blindly indexing into it. Otherwise you'll likely crash if your input data's format doesn't match your assumptions.
(BTW, do not use valueForKey for this. That is KVO code, and while it usually works, it is not the same as using NSArray and NSDictionary methods to fetch the data, and sometimes does not work correctly.)

How to replace object index in NSMutableArray in iPhone

I have two different arrays and I want to check firstArray objects and accordingly insert objects in second array.If my firstArray contains particular object then at that index, I am trying insert value in secondArray.
Currently, I am inserting values like :
[secondArray replaceObjectAtIndex:0 withObject:transIdArray];
[secondArray replaceObjectAtIndex:1 withObject:fullCaseArray];
[secondArray replaceObjectAtIndex:2 withObject:caseTitleArray];
[secondArray replaceObjectAtIndex:3 withObject:filingDateArray];
My problem is, If in firstArray transIdArray is at 2 index then my these two arrays data getting mismatched.Please suggest me better way to check add insert values in arrays. Thanks.
NSArray elements are naturally packed together, not sparse, like C arrays can be. To accomplish what you want, the secondArray needs to carry placeholders that are considered non-objects semantically by your app. [NSNull null], an instance of NSNull (not to be confused with nil) is a common choice.
You could initialize one or both arrays like this:
for (NSInteger i=0, i<SOME_KNOW_MAX_LENGTH; ++i) {
[secondArray addObject:[NSNull null]];
}
Then an instance of NSNull in the second array means 'there's nothing at this index in this array corresponding to firstArray'. And you can check if that condition holds for a given index like this:
id secondArrayElement = secondArray[index];
if ([secondArrayElement isMemberOfClass:[NSNull class]]) { // ...
As an aside - often, when I find myself needing to coordinate parallel arrays, it usually means I have some undone representational work, and what I really need is a single array with a more thoughtful object, or the containing object must be more thoughtfully designed.

How to import array attribute with MagicalRecord into CoreData

I am importing a json where the objects have many array attributes such as images:
"images": [
"model1.jpg",
"model2.jpg"
],
"models": []
"one model",
"another model",
"third model"
]
Currently I just do:
[ExampleObject MR_importFromArray:objectArrayFromJson];
but these arrays break this auto import since it can't auto fit NSArray to NSData (the binary from when setting the model up in Xcode).
Is there anyway to modify the Model class files (like custom setters/getters) so the MagicalRecord can import my array and store it in the entitys´ attribute and when I retrieve it I get an NSArray in return?
I solved this myself after some research and I want to share it to whoever might get stuck with same problem.
My problem was that I wanted to save an NSArray into an entity attribute of type NSData. To be able to do this with MagicalRecord I needed to implement a method in my NSManagedObject m-file like this:
- (BOOL) importImages: (id) array {
NSData *imagesData = [NSKeyedArchiver archivedDataWithRootObject:array];
self.images = imagesData;
return YES;
}
so import<;attribute-name without ;> the method must be called.
EDIT:
According to this page you return YES if your code process the data. Return NO if you want MagicalImport to continue processing the attribute and use the default import routines.

In Objective-C, using Core Data, how to fetch all of the Entity classes and their meta information?

I'd like to fetch all the entities I've created and filter all the ones that have a particular parent entity. In the end, I'm looking for a collection of the class names for all of these entities so I can iterate on them.
I couldn't find any info on how I can do this. Is it possible? How can it be done?
NSArray *allEntityNames = [[yourManagedObjectModel.entitiesByName allKeys] allObjects];
Gets you an array of all your entity string names, ordered alphabetically. Just calling entitiesByName on your NSManagedObjectModel gets you all the meta information you might want too but is very verbose.
If you want you can check for parent entities right in a block by seeing if the entity's parent entity is NSManagedObject or one of your subclasses instead, or do it after the block if you want to keep the "master list" for a few cases.
NSArray *allEntityNames = [[yourManagedObjectModel.entitiesByName keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
if (hasParent)
return YES;
else
return NO;
}] allObjects];

iOS -- updating data structures in new app version

I am not using core data. Just to keep it simple, let's say I have data which were formerly of type NSString, and now they are supposed to be objects of a custom class Person whose only ivar is a "name" ivar of type NSString. In the updated version of the app, I want my Person objects to have their "name" set to whatever the NSString was in the saved data. But suppose my people appear in lots of different places in the app, so telling it how to handle each one individually would be a pain.
What is the best way to handle this? In particular, is there some trick I can do to catch it in the un-archiving process? Or do I have to go through every un-archived object and turn the appropriate NSStrings into Person objects?
You can create a utility class that check the value that come back from your unarchiver, run it through this method. If the value is an NSString, then you can construct a new Person object, if not, then just returns that object back.
+ (Person *)personFromStringOrPersonObject:(id)object {
if ([object isKindOfClass:[NSString class]]) {
// Construct your Person object
Person person = [Person new];
person.name = object;
return person;
} else {
return object;
}
}

Resources