Creating Array with properties for each item in Objective-c - objective-c

tell me please, how do I create an array in which each element will have a number of properties. For example:
array:
|
|-item 1 ( property_1-"Name1", property_2-"LastName1", property_3-"Age1");
|-item 2 ( property_1-"Name2", property_2-"LastName2", property_3-"Age2");
|-item 3 ( property_1-"Name3", property_2-"LastName1", property_3-"Age2");
|-…
In this case, the different elements of an array can have one and the same property, such as in the code posted above - "item 3" has the "property 2" is the same as in "item 1", and "property 3" is the same as in "item 2"
Tell me, please, how best to do it and, if not difficult, write a simple example or a link to some tutorial.
Thank you in advance)

There are two methods that I would suggest:
1. Use a class to store all the properties
Here's an example:
#interface Wrapper : NSObject
#property (nonatomic, assign) NSString* property_1;
#property (nonatomic, assign) NSString* property_2;
#property (nonatomic, assign) NSString* property_3;
#end
Then you can use it as a dictionary:
NSString* value=[myWrapperInstance valueForKey: #"property_1"];
But here comes the alternative solution:
1. Use a NSDictionary to store all the properties
NSDictionary* dict= #{ #"property_1" : #"Name1" ,#"property_2" : #"Name2", #"property_3" : #"Name3" };
Then the solution comes easy:
NSMutableArray* objects=[NSMutableArray new];
for(int i=0; i<N; i++)
{
NSDictionary* dict= #{ #"property_1" : #"Name1" ,#"property_2" : #"Name2", #"property_3" : #"Name3" };
[objects addObject: dict];
}

Sounds like you want an NSArray of NSDictionary objects:
NSDictionary *dict1 = [NSDictionary dictionaryWithObjectsAndKeys:#"Name1", #"property_1", #"LastName1", #"property_2", #"Age1", #"property_3", nil);
NSDictionary *dict2 = [NSDictionary dictionaryWithObjectsAndKeys:#"Name2", #"property_1", #"LastName2", #"property_2", #"Age2", #"property_3", nil);
NSDictionary *dict3 = [NSDictionary dictionaryWithObjectsAndKeys:#"Name3", #"property_1", #"LastName3", #"property_2", #"Age3", #"property_3", nil);
NSArray *array = [NSArray arrayWithObjects:dict1, dict2, dict3, nil];
If you want to update this later then you should use NSMutableDictionary and NSMutableArray, respectively.
If you are not using ARC, the you need to release objects when you are finished with them.

Related

Unable to create mutable copy of NSDictionary

UPDATE: Now working (added fixes as suggested - Thanks!)
I've been trying to clone an NSDictionary of employee info. The main NSDictionary is created in a different class and passed along in prepareForSegue. I want to be able to create a mutable copy of that NSDictionary in another class which can then update the employee info and send it off to another class for processing so I still have the original unchanged dataset to work with at a later time. I've found a few different examples on Stack, but nothing I could get working. When I break on the btn_click method and examine the local pp object after the ..objectForKey call, pp is still nil. What have I done wrong here?
obj_person.h
#import <Foundation/Foundation.h>
#interface obj_person : NSObject
#property (strong,nonatomic) NSString *personID;
#property (strong, nonatomic) NSString *personName;
#property (strong, nonatomic) NSString *personTitle;
#end
obj_person.m
#import "obj_person.h"
#implementation obj_person
#synthesize personID = _personID;
#synthesize personName = _personName;
#synthesize personTitle = _personTitle;
#end
viewcontroller.m
#import "ViewController.h"
#import "obj_person.h"
#interface ViewController ()
#end
#implementation ViewController
int mCounter = 1;
NSMutableDictionary *mCopy;
NSMutableDictionary *mNsd;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *arnames = [[NSArray alloc] initWithObjects:#"mary", #"jane", #"stan", #"cartman", nil];
NSArray *arkeys = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2],[NSNumber numberWithInt:3], [NSNumber numberWithInt:4], nil];
mNsd = [[NSMutableDictionary alloc] initWithCapacity:[arnames count]];
int i = 0;
for (NSString *name in arnames)
{
obj_person *p = [[obj_person alloc] init];
p.personID = [arkeys objectAtIndex:i];
p.personName = name;
[mNsd setObject:p forKey:p.personID];
i++;
}
mCopy = [mNsd mutableCopy];
}
- (IBAction)btn_click:(id)sender
{
NSLog (#"%d original items", [mNsd count]);
obj_person *pp = [mCopy objectForKey:[NSNumber numberWithInt:mCounter]];
NSLog(#"%#", pp.personName);
pp.personName = #"Gerald";
if (++mCounter > [mCopy count])
mCounter = 1;
}
#end
Don't define:
NSMutableDictionary *mCopy;
NSMutableDictionary *mNsd;
Outside of the #interface and #implementation. They should be instance variables, so define instance variables or use properties to define them.
It's a good job you don't use n from:
for (NSArray *n in arnames)
because it isn't an NSArray, it's an NSString. You should fix that and you should probably both name it better than n and use it.
This:
obj_person *pp = [mCopy objectForKey:[NSNumber numberWithInt:1]];
fails because the key you originally stored with is an NSString instance and the thing you are using to try to get the data out is an NSNumber instance (so they can never match).
You might try:
mCopy = [mNsd mutableCopy];
[mCopy retain]
One theory is that the mutableCopy returns is an autoreleased object and it's being killed off before the btn_click function fires. According to this post: Retain/release of returned objects, mutableCopy should not be autoreleasing the array, but bugs do happen.
Else, maybe try iterating through with a for-loop instead.
int cnt = [arnames count];
for(int i=0; i<cnt; i++)
...

Store key / value of NSMutableDictionary to another NSMutableDictionary

So I have three NSMutableDictionary's like this:
.h file
NSMutableDictionary *myContainer;
NSMutableDictionary *myD1;
NSMutableDictionary *myD2;
#property (nonatomic, retain) NSMutableDictionary *myContainer;
#property (nonatomic, retain) NSMutableDictionary *myD1;
#property (nonatomic, retain) NSMutableDictionary *myD2;
.m file
#synthesize myContainer;
#synthesize myD1;
#synthesize myD2;
( init )
self.myContainer = [[NSMutableDictionary alloc] init];
self.myD1 = [[NSMutableDictionary alloc] init];
self.myD2 = [[NSMutableDictionary alloc] init];
Now I want to add values or positions in the dictionary to myContainer from myD1 and myD2
Pseudo:
[myD1 setValue:foo forKey:#"bar"];
[foo retain];
[myD2 setValue:hello forKey:#"world"];
[hello retain];
So my question is how do I add specific key / value to myD1 and / or myD2 to myContainer? And then retrieve the key / value from them as well?
The below looks like what I need but I'm a newbie and the format I have differs.
Coming from PHP here is how I would structure this:
$myContainer = array();
$myD1 = array();
$myd2 = array();
$myD1['bar'] = 'foo';
$myD2['world'] = 'hello';
$myContainer['common_index'] = array($myD1, $myD2);
// Alternative
//$myContainer['common_index'] = array(0 => $myD1, 1 => $myD2);
// Retrieving values from $myD1
echo "Value: ".$myContainer['common_index'][0]['bar']."\n";
echo "Value: ".$myContainer['common_index'][1]['world']."\n";
// Alternative
foreach($myContainer['common_index'] as $array) {
foreach($array as $index => $value) {
echo "Index: {$index} Value: {$value} \n";
}
}
Output:
Value: foo
Value: hello
Index: bar Value: foo
Index: world Value: hello
Related:
NSMutableDictionary with single key holding many values in Objective-C programming
Add your myD1 myD2 dictionaries in an Array and set it to the myContainer dictionary as below :
NSMutableArray *array = [NSMutableArray arrayWithObjects:myD1, myD2, nil];
[myContainer setObject:array forKey:#"common_index"];
And for retreiving them :
NSMutableDictionary *myD1Retrieved = [[myContainer objectForKey:#"common_index"] objectAtIndex:0];
NSMutableDictionary *myD2Retrieved = [[myContainer objectForKey:#"common_index"] objectAtIndex:1];
To add data to myContainer:
[myContainer setValue:[mD1 valueForKey:#"bar"] forKey:#"bar"];
[myContainer setValue:[mD2 valueForKey:#"world"] forKey:#"world"];
For retrieval from myContainer:
Object *firstObject = [myContainer valueForKey:#"world"];
Object *secondObject = [myContainer valueForKey:#"bar"];
Object stands for the type of value for world and bar keys.
go on..

SBJSON encode Object who contain an array of another Object

i've a little json encode problem :
i need to encode an object format JSON with SBJSON before send it to a php server
At the moment this sample code work :
NSArray *arrayData = [NSArray arrayWithObjects:
user.id == nil ? [NSNumber numberWithInt:-1] : user.id,
ProfessionField.text, NameField.text, RPPSField.text, RPPSField.text,
NameField.text, SurnameField.text, StreetField.text,
TownField.text, CpField.text, MailField.text,
PhoneField.text, FaxField.text, MobileField.text,
// [user.horaires JSONRepresentation],
nil];
NSArray *arrayKey = [NSArray arrayWithObjects:
#"id", #"spe", #"name", #"rpps", #"cip",
#"name", #"surname", #"rue",
#"ville", #"cp", #"mail",
#"tel", #"fax", #"port",
// #"horaires",
nil];
NSDictionary *dataBrut = [NSDictionary dictionaryWithObjects:arrayData forKeys:arrayKey];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:dataBrut forKey:#"data"];
NSString *jsonRequest = [jsonDict JSONRepresentation];
The problem is when i need to send the "user.horaires" (here in comment)
Application CRASH at the JSON representation of this object.
this object is an Array of the following class :
#interface Horaire : NSObject
{
BOOL morning;
}
#property (nonatomic, strong) NSNumber *id;
#property (nonatomic, strong) NSString *open;
#property (nonatomic, strong) NSString *close;
Someone know how to succes to encode this ?
You shouldn't be including the JSON representation as a JSON item. JSON does not "escape" string data very well, so the embedded JSON (unless you separately "escape" it) will cause parsing to choke.
Instead you should place the dictionary or array that was used to produce the JSON representation (ie, "user.horaires" itself) in the location where you show the representation being produced and inserted. Then the entire structure will be JSON-encoded in one operation.
Ie:
NSArray *arrayData = [NSArray arrayWithObjects:
user.id == nil ? [NSNumber numberWithInt:-1] : user.id,
ProfessionField.text, NameField.text, RPPSField.text, RPPSField.text,
NameField.text, SurnameField.text, StreetField.text,
TownField.text, CpField.text, MailField.text,
PhoneField.text, FaxField.text, MobileField.text,
user.horaires,
nil];

Can't save to plist

I have my own object class from inherited from NSObject
#interface BlockedCell : NSObject
{
NSValue *gridValue;
NSString *name;
}
#property (nonatomic, retain) NSValue *gridValue;
#property (nonatomic, retain) NSString *name;
#end
So I try to create a few objects:
NSMutableDictionary *dict = [[dict alloc] init];
for (int i = 0; i < 5; ++i)
{
BlockedCell *block = [[BlockedCell alloc] init];
block.gridValue = [NSValue valueWithCGPoint: CGPointMake(0.0f, 0.0f)];
block.name = #"something";
[dict setObject: block forKey: [NSString stringWithFormat: #"item_%d", i]];
[block release];
}
if([dict writeToFile: path atomic: YES])
NSLog(#"Saved");
else
NSLog(#"Failed to save");
[dict release];
And what I get for the output is "Failed to save"..
If my dictionary does not contains any data, then it will output "Saved"
EDIT:
After I did more testing, I found out that actually is the NSValue causing the saving failed.
So what should I do if I want to save CGPoint into plist?
As you discovered, property lists cannot store NSValue objects directly. The supported classes are NSData, NSString, NSArray, NSDictionary, NSDate, and NSNumber, as documented in the NSPropertyListSerialization Class Reference.
The easiest workaround would be to use NSString instead of NSValue:
block.gridString = NSStringFromCGPoint(CGPointZero);
CGPoint point = CGPointFromString(block.gridString);
you cant save NSValue directly.In your case you have to save a point in the form ofstring use below line
CGPoint point = CGPointMake(10.0,20.0)
//you need to translate the point into a compatible "Plist" object such as NSString
//luckily, there is a method for that
[rectArray addObject:NSStringFromPoint(point)];
//save into a plist
.....
on retrieval of this value
CGPoint Point = CGPointFromString([rectArray objectAtIndex:0]);

Work with objects in NSArray

I need to work with objects in NSMutableArray. I have NSMutableArray called "Albums"
it contains objects "Album"
#interface Album : NSObject {
NSString *aid;
NSString *title;
NSString *ownerID;
}
I push few Album objects into "Albums" NSMutableArray, and i want to delete Album object where
"title" field is "HelloWorld" for example or something else. How to do this?
This should do:
NSArray *matchingObjects = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.title = %#", #"HelloWorld"]];
[array removeObjectsInArray:matchingObjects];