How to add NSDictionary as a value in Objective-C? - ios

I have a property:
#property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableDictionary<NSString *, NSString *>*>*mainDict;
So it is a dictionary with another dictionary as its value.
Now, when I wanna populate my dictionary, I do:
NSData *data = [json_string dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
for (NSString *key in [[json objectForKey:#"countries"] allKeys]) {
NSDictionary *innerDictionary = [json objectForKey:#"countries"][key];
[mainDict setObject:innerDictionary forKey:key];
}
when I debug, I see that my innerDictionary is correct and has its values but somehow my mainDict is not being filled.
Could you please tell me what I do wrong?

Declaring mainDict as a #property will create an instance variable in your class, but that variable will be nil.
You'll need to initialize the mainDict somewhere before your population code gets called, perhaps in your -init, -viewDidLoad, or somewhere appropriate for your app's architecture.
mainDict initialization should look like:
mainDict = [[NSMutableDictionary alloc] init];

Related

Add an object to a NSMutableArray using arrayWithObject

This is my code:
NSMutableArray* notifications = [NSMutableArray arrayWithObjects:myObject.dictionary, nil];
After creating the NSMutableArray I do this:
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:notifications options:NSJSONWritingPrettyPrinted error:&writeError];
How can I add other objects to the NSMutableArray notification?
I know I can do something like:
NSMutableArray* notifications = [NSMutableArray arrayWithObjects:object1.dictionary, object2.dictionary, object3.dictionary, nil];
but I want to add them after the creation of the NSMutableArray.
myObject contains this:
-(NSDictionary *)dictionary {
return [NSDictionary dictionaryWithObjectsAndKeys:self.name,#"name",self.category,#"category",self.note, #"note",self.dueDate, #"dueDate",self.creationDate, #"creationDate", nil];}
You can add one object as an array to an existing array as follows:
[notifications addObjectsFromArray: [NSArray arrayWithObject: object.dictionary]];
Alternatively, instead of arrayWithObject, you can also use the literal notation:
[notifications addObjectsFromArray: #[object.dictionary]];
You can add even more than one object at a time:
[notifications addObjectsFromArray: #[object1.dictionary, object2.dictionary]];

Building NSMutableArray from NSMutableDictionary resulting in NSException

I am a newbie in iOS development. I was trying to put the results of an NSMutableArray into an NSMutableString but this is resulting in an NSException.
Here is my code:
NSMutableArray *oldtableData = .......this is where I recieve card data;
NSError *error;
NSMutableData *tableDataUpdated = [[NSJSONSerialization dataWithJSONObject:oldtableData
options:0
error:&error] copy];
NSMutableDictionary *cardDictionary = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
For converting the cardDictionary into a NSMutableArray, I am using this piece of code (which is giving me an NSException)
NSMutableArray *type = [NSMutableArray array];
NSMutableArray *last4Digits = [NSMutableArray array];
[cardDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[type addObject:[obj valueForKeyPath:#"type"]];
[last4Digits addObject:[obj valueForKeyPath:#"last4Digits"]];
}];
But If I exclude the above code and try NSLog with this piece of code
NSLog(#"JSON: %#",cardDictionary);
Console will give a proper json result; something like this:
JSON: (
{
cardPciId = "###########";
fingerPrint = ###########;
last4Digits = 4321;
type = Mastercard;
},
{
cardPciId = "###########";
fingerPrint = ###########;
last4Digits = 1234;
type = Visa;
}
)
I am trying to convert this into two Arrays, one with all the "type"s and another one with all "last4Digits". But this is what I get
Uncaught exception: -[__NSCFArray enumerateKeysAndObjectsUsingBlock:]:
unrecognized selector sent to instance 0x7ff7060badf0
I tried to hover through StackOverFlow to find a solution but none of them seem to be working. :(
It looks like cardDictionary is actually an NSArray instance containing the dictionaries. So, you should iterate through the array, and get type and last4Digits from each dictionary using objectForKey instead of valueForKeyPath:
NSArray *cardDictionaries = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
NSMutableArray *type = [NSMutableArray array];
NSMutableArray *last4Digits = [NSMutableArray array];
[cardDictionaries enumerateObjectsUsingBlock:^(NSDictionary *cardDictionary, NSUInteger idx, BOOL *stop) {
[type addObject:[cardDictionary objectForKey:#"type"]];
[last4Digits addObject:[cardDictionary objectForKey:#"last4Digits"]];
}];
There is a lot going on here, but I want to point one thing out.
Table data is being serialized to JSON.
NSMutableData *tableDataUpdated = [[NSJSONSerialization dataWithJSONObject:oldtableData
options:0
error:&error] copy];
Next, the data that was just serialized is de-serialized. It will always be the same array.
NSMutableDictionary *cardDictionary = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
You will always get the same data back. You don't need to do the JSON step at all.

Iterating over a NSDictionary to add values to an object

I am trying to iterate through a NSDictionary and add all the values in that dictionary to an object. So i added new cocoa class file to my project and subclassed it with NSObject. (named it customClass)
In my custom class.h:
- (void)printDir; // iterate through the direcory and print it.
#property (nonatomic, retain) NSMutableDictionary *objDictionary;
In customClass.m the defination of printDir method is as:
- (void)printDir {
_objDictionary = [[NSMutableDictionary alloc ]init];
for(id key in _objDictionary) {
id value = [_objDictionary objectForKey:key];
NSLog(#"Values in Objects Dictionary");
NSLog(#"%#",value);
}
}
In my ViewController.m i am trying to iterate through a NSDirectory and add all the values of that directory to the NSMutableDictionary of the object. For which,
for(id key in jsonDictionary.allKeys) {
id value = [jsonDictionary objectForKey:key];
[obj.objDictionary setObject:value forKey:key];
}
When i run the project the printDir method of the object get called, however the for loop does not execute. Can someone point out where i am going wrong. Thanks.
_objDictionary = [[NSMutableDictionary alloc ]init];
Change this line in your printDir method to init method of your custom class. The problem now is each time when you reach your printDir method, it is re-assigning the _objDictionary to nil. So the loop will not execute
In printDir Function you are allocating a dictionary objDictionary again.... so it over right your actual value supplies by your view controller .... You just change your function to this
In .h file
- (void)printDirwithDictionary :(NSMutableDictionary *)dict;
And in .m file
- (void)printDirwithDictionary:(NSMutableDictionary *)dict {
_objDictionary = [[NSMutableDictionary alloc] initWithDictionary:dict]
for(id key in _objDictionary) {
id value = [_objDictionary objectForKey:key];
NSLog(#"Values in Objects Dictionary");
NSLog(#"%#",value);
}
}
In ViewController.m Follow This code
NSMutableDictionary *dictToPass = [[NSMutableDictionary alloc]init];
for(id key in jsonDictionary.allKeys) {
id value = [jsonDictionary objectForKey:key];
[dictToPass setObject:value forKey:key];
}
[obj printDirWithDictionary:dictToPass];
And Call from View Controller will be like this
And Then Follow the sameprocedure . Hope This will Work Properly .

Populating NSmutableDictionary error

Greeting. I have a NSmutableDictionary and want to populate it.
- (IBAction)addCourse:(UIButton *)sender {
//NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
//To add content and keys
NSInteger numRow=[picker selectedRowInComponent:kNumComponent];//0=1st,1=2nd,etc
NSInteger SeaRow=[picker selectedRowInComponent:kSeaComponent];//0=fall,1=spring,2=summer
NSInteger CourseRow=[picker selectedRowInComponent:kCourseComponent];
NSString *num=Number[numRow];
NSString *season=Season[SeaRow];
NSString *course=Course[CourseRow];
NSString *AddKey=[NSString stringWithFormat:#"%# %#",num,season];
[contents setObject:[NSMutableArray arrayWithObjects:course, nil] forKey:AddKey];
// NSLog(#"%#", key);//test key here, it works
NSLog(#"Dictionary: %#", [contents description]);//test dictionary here
...}
Here, I have a button, when I push it, num and season and form a key, and the related course will be add to the dictionary. However, when I test it with
NSLog(#"Dictionary: %#", [contents description]);
to show all the content in the dictionary, Only the last record in my selection is shown. In other words, when populating the dictionary, the previous data were override by the later one. What is the problem please?
Update: Thanks for Javier's advice. It fix this problem. But now in the new situation, only one key can hold one content. The following content will override the old one, why is that please?
NSMutableDictionary *contents is not retained by any object of your controller and when the method finishes, that object will be released automatically .
Try declaring contents as a property:
#property (nonatomic,strong) NSMutableDictionary *contents;

Save array of objects on the disc with JSONModel (IOS)

I read a lot of docs about this but I can't really understand how it precisely works.
I would like to save my apps data in JSON format on the disc of the phone.
I have a array of objects of this type:
#interface ObjectA : NSObject
#property (strong, nonatomic) NSMutableArray* names1;
#property (strong, nonatomic) NSMutableArray* names2;
#property (strong, nonatomic) NSMutableArray* names3;
#property (strong, nonatomic) NSMutableArray* names4;
#property (strong, nonatomic) NSString* nameObjectA;
#property (assign) int number;
By using JSONModel, how can I transforme a "NSMutableArray *ObjectA" in a JSON file and after that read this file back in the app.
Thanks.
- (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary {
if(self = [self init]) {
// Assign all properties with keyed values from the dictionary
_nameObjectA = [jsonDictionary objectForKey:#"nameAction"];
_number = [[jsonDictionary objectForKey:#"number"]intValue];
_actions1 = [jsonDictionary objectForKey:#"Action1"];
_actions2 = [jsonDictionary objectForKey:#"Action2"];
_actions3 = [jsonDictionary objectForKey:#"Action3"];
_actions4 = [jsonDictionary objectForKey:#"Action4"];
}
return self;
}
- (NSArray *)locationsFromJSONFile:(NSURL *)url {
// Create a NSURLRequest with the given URL
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:30.0];
// Get the data
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
// Now create a NSDictionary from the JSON data
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// Create a new array to hold the locations
NSMutableArray *actions = [[NSMutableArray alloc] init];
// Get an array of dictionaries with the key "actions"
NSArray *array = [jsonDictionary objectForKey:#"actions"];
// Iterate through the array of dictionaries
for(NSDictionary *dict in array) {
// Create a new Location object for each one and initialise it with information in the dictionary
Action *action = [[Action alloc] initWithJSONDictionary:dict];
// Add the Location object to the array
[actions addObject:action];
}
// Return the array of actions objects
return actions;
}
The demo app that comes with JSONModel includes an example how to store your app's data via a JSONMOdel: https://github.com/icanzilb/JSONModel
Check the code in this view controller: https://github.com/icanzilb/JSONModel/blob/master/JSONModelDemo_iOS/StorageViewController.m
The logic is that you can export your model to a json string or json compliant dictionary and then save those to the disc using the standard APIs. Check the code
In ObjectA you define two methods -- toDictionary and initWithDictionary. Roughly:
-(NSDictionary*) toDictionary {
return #{#"names1":names1, #"names2":names2, #"names3":names3, #"names4":names4, #"nameObjectA":nameObjectA, #"number":#(number)};
}
- (id) initWithDictionary:(NSDictionary*) json {
self = [super init];
if (self) {
self.names1 = json[#"names1];
... etc
self.nameObjectA = json[#"nameObjectA"];
self.number = json[#"number"].intValue;
}
return self;
}
Run the dictionary created by toDictionary through NSJSONSerialization to produce an NSData and write that to a file. To read, fetch the NSData from the file, run back through NSJSONSerialization, and use initWithDictionary.
Of course, this assumes that the contents of your dictionaries are "JSON legal" -- strings, numbers, NSArrays, or other NSDictionarys.
And, if the arrays/dictionaries being initialized are mutable, one should specify the "MutableContainers" option on NSJSONSerialization.

Resources