Insertion in one array effects other array? - ios

I have 2 NSMutableArray.I am adding custom class objects into them. I have initialized them as below.
arr_post=[[NSMutableArray alloc]init];
copy_arr_user_post=[[NSMutableArray alloc]init];
I am adding the objects into them like this.
for(i=0;i<[arr_main count];i++)
{
Post *obj=[[Post alloc]init];
obj.name=#"abc";
obj.gender=#"male";
[arr_post addObject:obj];
[copy_arr_user_post addObject:obj];
}
Now when i remove object from arr_post & insert again then it is also effected in another array.
Post *post=[arr_post objectAtIndex:indexPath.row];
[arr_post removeObjectAtIndex:indexPath.row];
post.name=#"def";
[arr_post addObjectAtIndex:indexPath.row];
then def is also added in second array.

You misunderstand how arrays work.
Arrays store references to objects, not the objects themselves. Its a bit like keeping people's phone numbers. If I have a list of 10 phone numbers and you have the same list of phone numbers, and the person at index 1 in my list moves to a new address, when you call your person at index one and ask for their address they will give you the changed address too.
Both arrays point to the same objects.
If you change settings on one of your objects, you will see those changes if you look up the object in either array.
If you want your arrays to contain independent objects then implement NSCopying in your custom class and use code like this:
for(i=0;i<[arr_main count];i++)
{
Post *obj=[[Post alloc]init];
obj.name=#"abc";
obj.gender=#"male";
[arr_post addObject:obj];
Post objectCopy = [obj copy]; //create a copy of our object
[copy_arr_user_post addObject: objectCopy]; //insert copy into other array
}
But again, to do that you need to teach your custom Post class to conform to the NSCopying protocol so it understands the copy message. Take a look at the docs on the NSCopying protocol for more information.

Of course it does affect the other array because both arrays contain the same (identical) object.
In Objective-C objects are reference types. That means a pointer is stored in the arrays respectively which points to the same object.
If you want to have different objects you have to copy them for example
[copy_arr_user_post addObject:[obj copy]];

This happens because arrays store pointers to the data not the actual data.
if you want to have two different copies of an object you can use this method:
for(i=0;i<[arr_main count];i++)
{
Post *obj=[[Post alloc]init];
obj.name=#"abc";
obj.gender=#"male";
NSData* objectData = [NSKeyedArchiver archivedDataWithRootObject: obj];
Post* obj2= [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
[arr_post addObject:obj];
[copy_arr_user_post addObject:obj2];
}
OR you can simply declare two objects:
for(i=0;i<[arr_main count];i++)
{
Post *obj1=[[Post alloc]init];
Post *obj2=[[Post alloc]init];
obj1.name=#"abc";
obj1.gender=#"male";
obj2.name=#"abc";
obj2.gender=#"male";
[arr_post addObject:obj1];
[copy_arr_user_post addObject:obj2];
}

Related

Magic command for extracting an array of names from an array of NSPropertyDescription objects

I have this array with a bunch of NSPropertyDescription objects. These objects have a property called name.
I want to extract an array containing just the names of all these objects.
Ok, I can do this:
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSPropertyDescription *property in anEntity) {
[array addObject:property.name];
}
but I know objective-c has a lot of magical commands to extract stuff from arrays of objects.
How do I do that using one of those magical commands?
thanks.
Key-Value Coding should do the trick:
NSArray *names = [arrayOfPropertyDescriptions valueForKey:#"name"];
For an array, valueForKey returns an array containing the results of invoking valueForKey: using the key on each of the array's objects.

Keep NSArray original order in NSCountedSet

I have an NSArray and I need to get data from two keys and put together in a NSMutableDictionary. One key has stringvalues and the other NSNumbervalues. When I try to create NSCountedSetwithout adding the keys I want to use to separate arrays, it doesn't work, because the objects are not identical, basically, I need to check if objectId is identical, don't matter if the other keys are different.
Here is the initial code:
for (PFObject *objeto in objects) {
PFObject *exercicio = objeto[#"exercicio"];
NSString *string = exercicio.objectId;
NSNumber *nota = objeto[#"nota"];
[exercicios addObject:string];
[notas addObject:nota];
So I create two NSMutableArraysand store the values I need. When I logthe arrays after this, they are perfectly ordered, meaning the NSStringis in the same indexof the NSNumberit belongs to in the other array. So far, so good.
Now, when I create the NSCountedSetwith the strings, it changes the order.
NSCountedSet *countedExercicios = [[NSCountedSet alloc] initWithArray:exercicios];.
My goal is to sum the NSNumbers pertaining to an specific object, therefore, when the order changes, I lose the connection between the two arrays.
I'm not sure what I could do to solve this problem, or even if there's a different approach to achieve the result I need.
You can create NSDictionary and add it to array. You will have just one array and you won't lose the connection, you can use objectId as a key and NSNumber as a value:
for (PFObject *objeto in objects) {
PFObject *exercicio = objeto[#"exercicio"];
NSString *string = exercicio.objectId;
NSNumber *nota = objeto[#"nota"];
NSDictionary *dict = #{string: nota};
[newArray addObject: dict];
}
When you need get all key (objectId) you can use NSPredictate.
Hope this help

How to populate an array with dictionaries containing certain key/values

I'm working with a plist file at the moment but intend to switch over to json when the backend is finally built. So for the moment my plist is an array that contains a bunch of dictionaries.
I'd like to use this information to create a new array containing only the dictionaries with certain values.
For example. My plist contains a bunch of locations like so:
key: location value:example place name here
key: type value:indoor
I want to build an array containing only those with "indoor" set as the type value.
And then perhaps a second one containing all "outdoor" locations.
What's the best way to go about doing this, or perhaps I can be directed to a tutorial of some sort.
Thanks.
Simply loop through your array and add the qualifying dictionaries to a new array.
NSMutableArray *arrayIndoor = [NSMutableArray array];
NSMutableArray *arrayOutdoor = [NSMutableArray array];
NSString *type;
for (NSDictionary *dict in arrayPList) {
type = [dict objectForKey:#"type"];
if ([type isEqualToString:#"indoor"])
[arrayIndoor addObject:dict];
else if ([type isEqualToString:#"indoor"])
[arrayOutdoor addObject:dict];
}
All you are really needing to do is sort the array into two arrays. There isn't a direct method that I have seen that will do this for you. My suggestion would be to use a fast enumeration over the array and conditionally break it into two new arrays.
NSMutableArray *locations = [[NSMutableArray alloc] init];
NSMutableArray *type = [[NSMutableArray alloc] init];
for (NSDictionary *dict in MyPlistArray) {
if ([dict valueForKey:#"locationKey"]) {
[locations addObject:dict];
} else if ([dict valueForKey:#"typeKey"]) {
[type addObject:dict];
}
}
You might need to use a different method for determining which key to put in each array, but you get the general idea.
Also I'm assuming that you would want the arrays of dictionaries to persist after, so you can just set those up as properties instead of local variables.

Iam adding the array in to the dictionary then remove the all objects from array

Iam adding the array in to the dictionary then remove the all objects from array.
When i print the dictionary it is also shows empty.Means the array data present in dictionary also removing.
if ([[[array objectAtIndex:0]objectAtIndex:i] isEqualToString:[filteredAry objectAtIndex:j]])
{
[menuAry addObject:[array1 objectAtIndex:i]];
}
[tempDict setValue:menuAry forKey:[filteredAry objectAtIndex:j]];
[menuAry removeAllObjects];
Why the tempdict shows empty?
The array you're adding to the dictionary is the very same object as the one you're removing all objects from. Adding it to the dictionary does not create a new object, it just adds a reference to the same object.
If you want to separate them, you should add a copy to the dictionary, like so:
NSMutableArray *copiedArray = [[menuAry mutableCopy] autorelease];
[tempDict setObject:copiedArray forKey:[filteredAry objectAtIndex:j]];
//...
If you use ARC, you can leave out the autorelease.

What's the standard convention for creating a new NSArray from an existing NSArray?

Let's say I have an NSArray of NSDictionaries that is 10 elements long. I want to create a second NSArray with the values for a single key on each dictionary. The best way I can figure to do this is:
NSMutableArray *nameArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (NSDictionary *p in array) {
[nameArray addObject:[p objectForKey:#"name"]];
}
self.my_new_array = array;
[array release];
[nameArray release];
}
But in theory, I should be able to get away with not using a mutable array and using a counter in conjunction with [nameArray addObjectAtIndex:count], because the new list should be exactly as long as the old list. Please note that I am NOT trying to filter for a subset of the original array, but make a new array with exactly the same number of elements, just with values dredged up from the some arbitrary attribute of each element in the array.
In python one could solve this problem like this:
new_list = [p['name'] for p in old_list]
or if you were a masochist, like this:
new_list = map(lambda p: p['name'], old_list)
Having to be slightly more explicit in objective-c makes me wonder if there is an accepted common way of handling these situations.
In this particular case Cocoa is not outdone in succinctness :)
NSArray *newArray = [array valueForKey:#"name"];
From the NSArray documentation:
valueForKey:
Returns an array containing the
results of invoking valueForKey: using
key on each of the receiver's objects.

Resources