NSInternalInconsistencyException for NSMutableArray - ios

I'm trying to add objects to an NSMutableArray but it keeps giving me this error.:
NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object
I have researched this problem, and I'm not doing anything wrong that past people have done, so I have no idea what's wrong. Here is my code:
Group.h
#property (strong, nonatomic) NSString *custom_desc;
#property (strong, nonatomic) NSMutableArray *attributes; //I define the array as mutable
Group.m
#import "Group.h"
#implementation Group
-(id)init
{
self = [super init];
if(self)
{
//do your object initialization here
self.attributes = [NSMutableArray array]; //I initialize the array to be a NSMutableArray
}
return self;
}
#end
GroupBuilder.m
#import "GroupBuilder.h"
#import "Group.h"
#implementation GroupBuilder
+ (NSArray *)groupsFromJSON:(NSData *)objectNotation error:(NSError **)error
{
NSError *localError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
return nil;
}
NSMutableArray *groups = [[NSMutableArray alloc] init];
NSDictionary *results = [parsedObject objectForKey:#"result"];
NSArray *items = results[#"items" ];
for (NSDictionary *groupDic in items) {
Group *group = [[Group alloc] init];
for (NSString *key in groupDic) {
if ([group respondsToSelector:NSSelectorFromString(key)]) {
[group setValue:[groupDic valueForKey:key] forKey:key];
}
}
[groups addObject:group];
}
for(NSInteger i = 0; i < items.count; i++) {
//NSLog(#"%#", [[items objectAtIndex:i] objectForKey:#"attributes"]);
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attributes"]; //this returns a NSArray object understandable
Group *g = [groups objectAtIndex:i];
[g.attributes addObjectsFromArray:[att mutableCopy]]; //I use mutable copy here so that i'm adding objects from a NSMutableArray and not an NSArray
}
return groups;
}
#end

Use options:NSJSONReadingMutableContainers on your NSJSONSerialization call.
Then all the dictionaries and arrays it creates will be mutable.

According to the error message you are trying to insert an object into an instance of NSArray, not NSMutableArray.
I think it is here:
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attrib`enter code here`utes"]; //this returns a NSArray object understandable
Items is fetched from JSON and therefore not mutable. You can configure JSONSerialization in a way that it creates mutable objects, but how exactly I don't know out of the top of my head. Check the references on how to do that or make a mutable copy:
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attributes"] mutableCopy];

Next try, considering your replies to the first attempt:
#import "Group.h"
#implementation Group
-(NSMutableArray*)attributes
{
return [[super attributes] mutableCopy];
}
#end

Related

dropbox V2 DBFILESmetadata for loop not incrementating

I'm having difficulty figuring out how to incorporate a counter so the "setObject" increments it's 'Save' in this for..loop.
NSMutableArray *NewArray = [NSMutableArray new];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for ( DBFILESMetadata *entry in result.entries) {
[dict setObject:entry.pathDisplay forKey:#"pathDisplay"];
[dict setObject:entry.name forKey:#"name"];
[NewArray addObject:dict];
}
I'm sure this is an easy answer,the last line is only saving the last item of result.entries. The NewArray has the correct count of items, but every item in the array is the last item of result.entries:
2017-04-13 16:47:58.876 Sites[11145:688352] NewArray (
{
name = 229;
pathDisplay = "/Sites/229";
},
{
name = 229;
pathDisplay = "/Sites/229";
}
).
I need to add a counter of some type to set the next object, just confused on where it should go.
Thanks in advance.
I figured this out:
for ( DBFILESMetadata *entry in result.entries) {
[imagePaths addObject:entry.pathDisplay];
[names addObject:entry.name];
}
for(int i=0; i<[result.entries count]; i++) {
dict = #{#"name": names[i], #"pathDisplay": imagePaths[i]};
[allObjects addObject:dict];
}
The dictionary item keys must be different. Otherwise, you see always last set item. Because the dictionary will overide when the save same key. So you can use just like below.
1.Solutions
NSMutableArray *NewArray = [NSMutableArray new];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
int i = 0;
for ( DBFILESMetadata *entry in result.entries) {
[dict setObject:entry.pathDisplay forKey:[NSString stringWithFormat:#"pathDisplay%d",i]];
[dict setObject:entry.name forKey:[NSString stringWithFormat:#"name%d",i]];
[NewArray addObject:dict];
i++;
}
2.Solution
Create a class that will hold the json property, just like a below.
HoldJsonDataClass.h
#interface HoldJsonDataClass : JsonData
#property (nonatomic,retain) NSString *name;
#property (nonatomic,retain) NSString * pathDisplay;
#end
HoldJsonDataClass.m
#implementation HoldJsonDataClass
#end
And than fill the class to the array. This solution is more clear.
for ( DBFILESMetadata *entry in result.entries) {
HoldJsonDataClass *holdJsonClass = [HoldJsonDataClass new];
holdJsonClass.name = entry.name;
holdJsonClass.pathDisplay = entry.pathDisplay;
[NewArray addObject:holdJsonClass];
}

Sort array in ascending order and remove duplicate values in objective- c

I have a horizontally and vertically scrollable table. I get the data for the header and first column from the web service(json). I want to sort the data in ascending order and remove duplicate data from both header and the first column. For removing duplicate values I used the following code:
-(void) requestFinished: (ASIHTTPRequest *) request
{
NSString *theJSON = [request responseString];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSMutableArray *jsonDictionary = [parser objectWithString:theJSON error:nil];
headData = [[NSMutableArray alloc] init];
NSMutableArray *head = [[NSMutableArray alloc] init];
leftTableData = [[NSMutableArray alloc] init];
NSMutableArray *left = [[NSMutableArray alloc] init];
rightTableData = [[NSMutableArray alloc]init];
for (NSMutableArray *dictionary in jsonDictionary)
{
Model *model = [[Model alloc]init];
model.cid = [[dictionary valueForKey:#"cid"]intValue];
model.iid = [[dictionary valueForKey:#"iid"]intValue];
model.yr = [[dictionary valueForKey:#"yr"]intValue];
model.val = [dictionary valueForKey:#"val"];
[mainTableData addObject:model];
[head addObject:[NSString stringWithFormat:#"%ld", model.yr]];
[left addObject:[NSString stringWithFormat:#"%ld", model.iid]];
}
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:head];
headData = [[orderedSet array] mutableCopy];
// NSSet *set = [NSSet setWithArray:left];
// NSArray *array2 = [set allObjects];
// NSLog(#"%#", array2);
NSOrderedSet *orderedSet1 = [NSOrderedSet orderedSetWithArray:left];
NSMutableArray *arrLeft = [[orderedSet1 array] mutableCopy];
//remove duplicate enteries from header array
[leftTableData addObject:arrLeft];
NSMutableArray *right = [[NSMutableArray alloc]init];
for (int i = 0; i < arrLeft.count; i++)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int j = 0; j < headData.count; j++)
{
/* NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.iid == %ld", [[arrLeft objectAtIndex:i] intValue]];
NSArray *filteredArray = [mainTableData filteredArrayUsingPredicate:predicate];*/
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.iid == %ld AND SELF.yr == %ld", [[arrLeft objectAtIndex:i] intValue], [[headData objectAtIndex:j] intValue]];
NSArray *filteredArray = [mainTableData filteredArrayUsingPredicate:predicate];
if([filteredArray count]>0)
{
Model *model = [filteredArray objectAtIndex:0];
[array addObject:model.val];
}
}
[right addObject:array];
}
[rightTableData addObject:right];
}
How will I sort the arrays in ascending order?
Please help.
OK, so you have a model object that looks something like this...
#interface Model: NSObject
#property NSNumber *idNumber;
#property NSNumber *year;
#property NSString *value;
#end
Note, I am intentionally using NSNumber and not NSInteger for reasons that will become clear.
At the moment you are trying to do a lot all in one place. Don't do this.
Create a new object to store this data. You can then add methods to get the data you need. Seeing as you are displaying in a table view sectioned by year and then each section ordered by idNumber then I'd do something like this...
#interface ObjectStore: NSObject
- (void)addModelObject:(Model *)model;
// standard table information
- (NSInteger)numberOfYears;
- (NSInteger)numberOfIdsForSection:(NSinteger)section;
// convenience methods
- (NSNumber *)yearForSection:(NSInteger)section;
- (NSNumber *)idNumberForSection:(NSInteger)section row:(NSInteger)row;
- (NSArray *)modelsForSection:(NSInteger)section row:(NSInteger)row;
// now you need a way to add objects
- (void)addModelObject:(Model *)model;
#end
Now to implement it.
We are going to store everything in one dictionary. The keys will be years and the objects will be dictionaries. In these dictionaries the keys will be idNumbers and the objects will be arrays. These array will hold the models.
So like this...
{
2010 : {
1 : [a, b, c],
3 : [c, d, e]
},
2013 : {
1 : [g, h, u],
2 : [e, j, s]
}
}
We'll do this with all the convenience methods also.
#interface ObjectStore: NSObject
#property NSMutableDictionary *objectDictionary;
#end
#implementation ObjectStore
+ (instancetype)init
{
self = [super init];
if (self) {
self.objectDictionary = [NSMutableDictionary dictionary];
}
return self;
}
+ (NSInteger)numberOfYears
{
return self.objectDictionary.count;
}
+ (NSInteger)numberOfIdsForSection:(NSinteger)section
{
// we need to get the year for this section in order of the years.
// lets create a method to do that for us.
NSNumber *year = [self yearForSection:section];
NSDictionary *idsForYear = self.objectDictionary[year];
return idsForYear.count;
}
- (NSNumber *)yearForSection:(NSInteger)section
{
// get all the years and sort them in order
NSArray *years = [[self.obejctDictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
// return the correct year
return years[section];
}
- (NSNumber *)idNumberForSection:(NSInteger)section row:(NSInteger)row
{
// same as the year function but for id
NSNumber *year = [self yearForSection:section];
NSArray *idNumbers = [[self.objectDictionary allKeys]sortedArrayUsingSelector:#selector(compare:)];
return idNumbers[row];
}
- (NSArray *)modelsForSection:(NSInteger)section row:(NSInteger)row
{
NSNumber *year = [self yearForSection:section];
NSNumber *idNumber = [self idForSection:section row:row];
return self.objectDictionary[year][idNumber];
}
// now we need a way to add objects that will put them into the correct place.
- (void)addModelObject:(Model *)model
{
NSNumber *modelYear = model.year;
NSNumber *modelId = model.idNumber;
// get the correct storage location out of the object dictionary
NSMutableDictionary *idDictionary = [self.objectDictionary[modelYear] mutableCopy];
// there is a better way to do this but can't think atm
if (!idDictionary) {
idDictionary = [NSMutableDictionary dictionary];
}
NSMutableArray *modelArray = [idDictionary[modelId] mutableCopy];
if (!modelArray) {
modelArray = [NSMutableArray array];
}
// insert the model in the correct place.
[modelArray addObject:model];
idDictionary[modelId] = modelArray;
self.objectDictionary[modelYear] = idDictionary;
}
#end
With all this set up you can now replace your complex function with this...
-(void) requestFinished: (ASIHTTPRequest *) request
{
NSString *theJSON = [request responseString];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *jsonDictionary = [parser objectWithString:theJSON error:nil];
for (NSDictionary *dictionary in jsonDictionary)
{
Model *model = [[Model alloc]init];
model.cid = [dictionary valueForKey:#"cid"];
model.idNumber = [dictionary valueForKey:#"iid"];
model.year = [dictionary valueForKey:#"yr"];
model.val = [dictionary valueForKey:#"val"];
[self.objectStore addModelObject:model];
}
}
To get the models out for a particular row then just use...
[self.objectStore modelsForSection:indexPath.section row:indexPath.row];
To get the number of sections in the tableview delegate method...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.objectStore numberOfYears];
}
No messing around with the model in the view controller.
Welcome to the MVC pattern.
There's a crap ton of code here but by placing all the code here you can remove all the complex code from your VC.
NSSet keeps only non-duplicate objects within themselves so to keep only unique objects in array you can use NSSet as -
Suppose you have array with duplicate objects
NSArray *arrayA = #[#"a", #"b", #"a", #"c", #"a"];
NSLog(#"arrayA is: %#", arrayA);
//create a set with the objects from above array as
//the set will not contain the duplicate objects from above array
NSSet *set = [NSSet setWithArray: arrayA];
// create another array from the objects of the set
NSArray *arrayB = [set allObjects];
NSLog(#"arrayB is: %#", set);
The output from the above looks like:
arrayA is: (
a,
b,
a,
c,
a
)
arrayB is: {(
b,
c,
a
)}
and to sort a mutable array in ascending order you can use NSSortDescriptor and sortUsingDescriptors:sortDescriptors. Also you need to provide the key on the basis of which array will be sorted.
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"key" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[array sortUsingDescriptors:sortDescriptors];
[sortDescriptor release];
Here you will get what you want.
//sort description will used to sort array.
NSSortDescriptor *descriptor=[[NSSortDescriptor alloc] initWithKey:#"iid" ascending:YES];
NSArray *descriptors=[NSArray arrayWithObject: descriptor];
NSArray *reverseOrder=[arrLeft sortedArrayUsingDescriptors:descriptors];
reverseOrder is your desire output.
there is another way you can sort objects that followed model.
NSArray *someArray = /* however you get an array */
NSArray *sortedArray = [someArray sortedArrayUsingComparator:^(id obj1, id obj2) {
NSNumber *rank1 = [obj1 valueForKeyPath:#"iid"];
NSNumber *rank2 = [obj2 valueForKeyPath:#"iid"];
return (NSComparisonResult)[rank1 compare:rank2];
}];
here sortedArray is our output.
you can replace same things for yr key as well.
This is what I did to sort the header data in ascending order and to remove duplicates from both header and leftmost column. Hope this will help others
NSOrderedSet *orderedSet3 = [NSOrderedSet orderedSetWithArray:head3];
headData3 = [[orderedSet3 array] mutableCopy];
[headData3 sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2)
{
return [str1 compare:str2 options:(NSNumericSearch)];
}];
NSOrderedSet *orderedSet4 = [NSOrderedSet orderedSetWithArray:left3];
NSMutableArray *arrLeft3 = [[orderedSet4 array] mutableCopy];
[leftTableData3 addObject:arrLeft3];

Parse PFObject save results to NSMutableArray

I'm looking to save values within from the PFObjet and save them to multiple NSMutableArrays. Let me explain. I'm download information from the Partisipants class within Parse. The Partisipants class contains multiple NSString values, such as name, phoneNumber, etc. I'm looking to scrape that information from the return value of the query, and add each instance of a new objectID to the NSMutableArray. Assume there are multiple rows, or userIDs to scrape into the NSMutableArray.
PFQuery *query = [PFQuery queryWithClassName:#"Partisipants"];
[query setLimit: 600];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded. The first 600 objects are available in objects
self.objectsFromParse = objects;
NSLog(#"%#", self.objectsFromParse);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
Edit
This is my return result for executing this query (personal information was modified):
(
"<Partisipants:S420zHiNFT:(null)> {\n additionalDonation = \"100.00\";\n emailAddress = \"somewhere#email.com\";\n emergencyPhone = 12345678901;\n hasArrived = NO;\n name = \"James\";\n phoneNumber = 12345678901;\n}",
"<Partisipants:9BpoFxO1zx:(null)> {\n additionalDonation = \"500.00\";\n emailAddress = \"someguy#email.com\";\n emergencyPhone = 12345678901;\n hasArrived = NO;\n name = \"Michael\";\n phoneNumber = 12345678901;\n}"
)
If you want to store emails, names, objectId's etc. each in new mutableArrays, you could do:
NSMutableArray * usernames = [NSMutableArray array];
NSMutableArray * emails = [NSMutableArray array];
NSMutableArray * objectIds = [NSMutableArray array];
for (PFObject * participant in objects) {
if (participant[#"name"]) [usernames addObject:participant[#"name"]];
if (participant[#"emailAddress"]) [emails addObject:participant[#"emailAddress"]];
[objectIds addObject:participant.objectId];
}
Create your array of participants. Then loop over them and build your mutable arrays(nameArray, email array, etc). Note that this is a very bad approach if some of the participants data is optional. How would you signify no email address for instance? You can't use nil in arrays so you'd have to represent it using NSNull or an empty string...
You may need help from KVC.
#import <Foundation/Foundation.h>
#interface Object : NSObject
#property (nonatomic, strong, readonly) NSString *name;
#property (nonatomic, strong, readonly) NSString *objectId;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
#end
#interface Object ()
#property (nonatomic, strong) NSDictionary *dictionary;
#end
#implementation Object
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
self.dictionary = dictionary;
}
return self;
}
- (NSString *)name
{
return self.dictionary[#"name"];
}
- (NSString *)objectId
{
return self.dictionary[#"objectId"];
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Object *object0 = [[Object alloc] initWithDictionary:#{#"name": #"victor", #"objectId": #"001"}];
Object *object1 = [[Object alloc] initWithDictionary:#{#"name": #"evan", #"objectId": #"002"}];
Object *object2 = [[Object alloc] initWithDictionary:#{#"name": #"gerry"}];
Object *object3 = [[Object alloc] initWithDictionary:#{#"name": #"tony", #"objectId": #"004"}];
NSArray *array = #[object0, object1, object2, object3];
NSArray *objectIds = [array valueForKey:#"objectId"];
NSLog(#"%#", objectIds);
NSArray *names = [array valueForKey:#"name"];
NSLog(#"%#", names);
NSArray *filteredObjectIds = [objectIds filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != nil"]];
NSLog(#"%#", filteredObjectIds);
NSMutableArray *mutableArray = [filteredObjectIds mutableCopy];
NSLog(#"%#", mutableArray);
}
return 0;
}
Console log:
2017-11-03 16:33:29.092837+0800 Test[50097:3891576] (
001,
002,
"<null>",
004
)
2017-11-03 16:33:29.093079+0800 Test[50097:3891576] (
victor,
evan,
gerry,
tony
)
2017-11-03 16:33:29.093317+0800 Test[50097:3891576] (
001,
002,
004
)
2017-11-03 16:33:29.093401+0800 Test[50097:3891576] (
001,
002,
004
)
Program ended with exit code: 0

How to convert NSDictionary to custom object

I have a json object:
#interface Order : NSObject
#property (nonatomic, retain) NSString *OrderId;
#property (nonatomic, retain) NSString *Title;
#property (nonatomic, retain) NSString *Weight;
- (NSMutableDictionary *)toNSDictionary;
...
- (NSMutableDictionary *)toNSDictionary
{
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:self.OrderId forKey:#"OrderId"];
[dictionary setValue:self.Title forKey:#"Title"];
[dictionary setValue:self.Weight forKey:#"Weight"];
return dictionary;
}
In string this is:
{
"Title" : "test",
"Weight" : "32",
"OrderId" : "55"
}
I get string JSON with code:
NSMutableDictionary* str = [o toNSDictionary];
NSError *writeError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:str options:NSJSONWritingPrettyPrinted error:&writeError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
Now I need to create and map object from JSON string:
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e];
This returns me filled NSDictionary.
What should I do to get object from this dictionary?
Add a new initWithDictionary: method to Order:
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
if (self = [super init]) {
self.OrderId = dictionary[#"OrderId"];
self.Title = dictionary[#"Title"];
self.Weight = dictionary[#"Weight"];
}
return self;
}
Don't forget to add initWithDictionary's signature to Order.h file
In the method where you get JSON:
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e];
Order *order = [[Order alloc] initWithDictionary:dict];
If the property names on your object match the keys in the JSON string you can do the following:
To map the JSON string to your Object you need to convert the string into a NSDictionary first and then you can use a method on NSObject that uses Key-Value Coding to set each property.
NSError *error = nil;
NSData *jsonData = ...; // e.g. [myJSONString dataUsingEncoding:NSUTF8Encoding];
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingOptionsAllowFragments error:&error];
MyObject *object = [[MyObject alloc] init];
[object setValuesForKeysWithDictionary:jsonDictionary];
If the keys do not match you can override the instance method of NSObject -[NSObject valueForUndefinedKey:] in your object class.
To map you Object to JSON you can use the Objective-C runtime to do it automatically. The following works with any NSObject subclass:
#import <objc/runtime.h>
- (NSDictionary *)dictionaryValue
{
NSMutableArray *propertyKeys = [NSMutableArray array];
Class currentClass = self.class;
while ([currentClass superclass]) { // avoid printing NSObject's attributes
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(currentClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if (propName) {
NSString *propertyName = [NSString stringWithUTF8String:propName];
[propertyKeys addObject:propertyName];
}
}
free(properties);
currentClass = [currentClass superclass];
}
return [self dictionaryWithValuesForKeys:propertyKeys];
}
Assuming that your properties names and the dictionary keys are the same, you can use this function to convert any object
- (void) setObject:(id) object ValuesFromDictionary:(NSDictionary *) dictionary
{
for (NSString *fieldName in dictionary) {
[object setValue:[dictionary objectForKey:fieldName] forKey:fieldName];
}
}
this will be more convenient for you :
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dictionary];}
return self;
}
The perfect way to do this is by using a library for serialization/deserialization
many libraries are available but one i like is
JagPropertyConverter
https://github.com/jagill/JAGPropertyConverter
it can convert your Custom object into NSDictionary and vice versa
even it support to convert dictionary or array or any custom object within your object (i.e Composition)
JAGPropertyConverter *converter = [[JAGPropertyConverter alloc]init];
converter.classesToConvert = [NSSet setWithObjects:[Order class], nil];
#interface Order : NSObject
#property (nonatomic, retain) NSString *OrderId;
#property (nonatomic, retain) NSString *Title;
#property (nonatomic, retain) NSString *Weight;
#end
//For Dictionary to Object (AS IN YOUR CASE)
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setValue:self.OrderId forKey:#"OrderId"];
[dictionary setValue:self.Title forKey:#"Title"];
[dictionary setValue:self.Weight forKey:#"Weight"];
Order *order = [[Order alloc]init];
[converter setPropertiesOf:order fromDictionary:dictionary];
//For Object to Dictionary
Order *order = [[Order alloc]init];
order.OrderId = #"10";
order.Title = #"Title;
order.Weight = #"Weight";
NSDictionary *dictPerson = [converter convertToDictionary:person];
Define your custom class inherits from "AutoBindObject". Declare properties which has the same name with keys in NSDictionary. Then call method:
[customObject loadFromDictionary:dic];
Actually, we can customize class to map different property names to keys in dictionary. Beside that, we can bind nested objects.
Please have a look to this demo. The usage is easy:
https://github.com/caohuuloc/AutoBindObject

How to initialize a dictionary from NSString to NSArray

I am trying to create a dictionary (Not sure whether it should be NSDictionary or NSMutableDictionary) from NSString to an array (Not sure whether it should be NSArray or NSMutableArray).
property:
#property(nonatomic, readonly) NSMutableDictionary * categories;
implementation:
#synthesize categories = _categories;
- (NSMutableDictionary *)categories{
if(! _categories) {
for(PFObject * each in self.products) {
NSString * currentcategory = [each valueForKey:#"subtitle"];
NSArray * currentlist = [_categories objectForKey:currentcategory];
if(! currentlist) {
currentlist = [[NSArray alloc] init];
}
NSMutableArray * newArray = [currentlist mutableCopy];
[newArray addObject:each];
NSArray * newlist = [NSArray arrayWithArray:newArray];
[_categories setObject:newlist forKey:currentcategory];
}
}
NSLog(#"After constructor the value of the dictionary is %d", [_categories count]);
return _categories;
}
From the debug NSLog I realize that the dictionary is empty after the construction. What is wrong here and how shall I change it?
After code line
if(! _categories) {
add
_categories = [NSMutableDictionary new];
If you did not initialize _category array somewhere in code then.
you must instantiate it inside
if(!_categories)
Your NSMutableArray _categories instance is not allocated and initialized yet.
To create instance of NSMutableArray just add
_categories = [NSMutableArray arrayWithCapacity:0];

Resources