iOS replaceObjectAtIndex Error - ios

I am new to iOS development, I encounter error when replaceObjectAtIndex. Any wrong with my codes? Please help.Thanks.
self.myArray =array;
for (NSDictionary *data in array) {
NSString *fbid = [data objectForKey:#"id"];
for (int index = 0; index < self.myPersonArray.count; index ++) {
for (IP_PERSON *person in self.myPersonArray) {
if ([person.UserDef2 isEqualToString:fbid]) {
[self.myArray replaceObjectAtIndex:index withObject:person];
break;
}
}
}
Error is :
Terminating app due to uncaught exception NSGenericException, reason: '*** Collection <__NSArrayM: 0xa34f6c0> was mutated while being enumerated.

You cannot use fast enumeration and mutate collection at the same time, hence the error message. You can resort to using an usual for-loop.

You're iterating over array, which is equal to self.myArray.
Further down, you're editing this array when you do: [self.myArray replaceObjectAtIndex:index withObject:person];
To resolve this, just make self.array a mutableCopy of the original array:
self.myArray = [array mutableCopy];

You can take another temporary array and iterate over that array, so you are enumerating and mutating different array.
NSArray *tempArray = [yourArray copy];
for (IP_PERSON *person in tempArray) {
if ([person.UserDef2 isEqualToString:fbid]) {
[self.myArray replaceObjectAtIndex:index withObject:person];
break;
}
}
[tempArray release];
Alternatively you can iterate without an enumerator, you can use regular for loop with starting index, exit condition and increment as you have done in outer loop.

You can..
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]
self.myArray =array;
for (NSDictionary *data in array) {
NSString *fbid = [data objectForKey:#"id"];
for (int index = 0; index < self.myPersonArray.count; index ++) {
for (IP_PERSON *person in self.myPersonArray) {
if ([person.UserDef2 isEqualToString:fbid]) {
[dictionary setObject:person forKey:#(index)]; //Notice this line
break;
}
}
}
}
And then..
for(id key in dictionary) {
[self.myArray replaceObjectAtIndex:[key intValue] withObject:[dictionary objectForKey:key]];
}

Related

How i know the index of Array object in NSCountedSet

This is my code for getting duplicate Device Contacts and i want to know how to get the index of the duplicate contacts
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:[Contact valueForKey:#"emailAddress"]];
for(id name in set){
if([name isEqual:[NSNull null]] || [name isEqualToString:#""]){
} else {
array=[[NSMutableArray alloc]init];
duplicateEmailDictionary =[NSMutableDictionary new];
if ([set countForObject:name]>1) {
for (int i=0; i<[set countForObject:name]; i++) {
[array addObject:name];
}
[duplicateEmailDictionary setObject:array forKey:#"emailAddress"];
[finalDuplicateEmail addObject:duplicateEmailDictionary];
}
}
}
A set is an unordered pool of unique objects. Since it's unordered, there is no integer index you can use to access specific elements of a set.
If you need index then use NSArray.

getting -[NSNull countByEnumeratingWithState:objects:count:]

Im trying to filter through an array and get rid of all the duplicate strings.
NSMutableArray *initialWomensCategoryArray = [NSMutableArray new];
for(NSArray *womensCategoryInnner in [objects valueForKey:#"womensCategory"])
{
for(id object in womensCategoryInnner)
{
[initialWomensCategoryArray addObject:object];
womensDataArray = [[NSMutableArray alloc]init];
for (id obj in initialWomensCategoryArray)
{
if (![womensDataArray containsObject:obj])
{
[womensDataArray addObject: obj];
}
}
}
}
Above Error want to say "You have getting NULL value" when you have add Object into array. So you have two possibility for this error
1) [initialWomensCategoryArray addObject:object]
2) [womensDataArray addObject: obj]
I think you have to check for the first one([initialWomensCategoryArray addObject:object])

Why app crashing while set a value to NSManagedObject in ios

Hi in my application I am setting the value for NSManagedObject while I am trying to set a value app is crashing.Here is the code and error message.
NSManagedObject *object3 = [threadManagedObjectContext objectWithID:[object1 objectID]] ;
for (int i=0;i<[array1 count];i++)
{
NSDictionary *keyValue=[array1 objectAtIndex:i];
[object3 setValue:[[keyValue allValues] lastObject] forKey:[[keyValue allKeys] lastObject]] ;
}
Error: Terminating app due to uncaught exception 'NSGenericException', reason:was mutated while being enumerated
Can any one please help me.
In your code (not the provided) , you're changing a collection while looping/iterating.
Example (not allowed):
for (MyClass *myClassObj in collectionOfMyClass) {
[myClassObj setClassVar: aVar]
}
Solution:
Make a temporary collection of the objects you want to set. Set all of them back outside of your loop.
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (MyClass *myClassObj in collectionOfMyClass) {
[tempArray addObject:aVar];
}
[myClassObj setClassVars: tempArray];
You can try below solution for updating the object...
NSManagedObject *object3 = [threadManagedObjectContext objectWithID:[object1 objectID]] ;
int i=0;
for (NSDictionary *keyValue in array1)
{
[[object3 setValue:[[keyValue allValues] lastObject] forKey:[[keyValue allKeys] lastObject]] ;i++;
}
NSError *error;
bool result = [[fetchedResultsController threadManagedObjectContext] save:&error];
if (!result) {
NSLog(#" error saving context, %#, %#", error, error.userInfo);
}
In your code while Looping/Enumerating you are setting value..So it is crashing...!
Hope it helps you....

How to remove all dictionaries from NSMutableArray based on the value in the dictionary

I am developing one iPad application.I have one NSMutableArray and NSMutableDictionary .These both are changeable based on the data from the web service.I need to remove some dictionary from my NSMutableArray based on the NSMutableDictionary values. Here I explain the situation through one example:
testArray =[{ language :"ESP"},{language :"ENG"},{language :"ENG"},{language :"FRH"}];
From the test array i need to remove the all Dictionaries which have key value language :"ENG".
I've written code like this:
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[testArray removeObjectAtIndex:i];
}
}
But it is not working. I think the problem is when I remove the dictionary from at index the array count is also reducing so the loop is executing based on new array count. Some help me to rewrite the code for get exact answer?
This is my favorite way, it's fast, clear and correct.
NSMutableArray *itemsToRemove = [NSMutableArray array];
for (id item in theArray) {
if ([item shouldBeRemoved])// Condition to check the key pair Value
[itemsToRemove addObject:item];
}
[theArray removeObjectsInArray:itemsToRemove];
Try this.
NSMutableArray *arrTemp = [[NSMutableArray alloc]initwithArray:testArray];
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[arrTemp removeObjectAtIndex:i];
}
}
[testArray removeAllObjects];
testArray = arrTemp;
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[testArray removeObjectAtIndex:i];
i--;
}
}
Replace your code with below code.
NSMutableArray *arrTemp = [NSMutableArray new];
for(int i =0;i<testArray.count;i++){
NSString *lang = [NSString stringWithFormat:#"%#", [testArray[i] objectForKey:#"language"]];
if([lang isEqualToString:#"ENG"]){
[arrTemp addObject:[NSNumber numberWithInt:i]];
}
}
for(int k=0;k<[arrTemp count];k++)
{
int ii = [[arrTemp objectAtIndex:k]intValue];
[testArray removeObjectAtIndex:ii];
}
let me know it is working or not!!!
Happy Coding!!!
I would implement that using NSPredicate:
NSMutableArray *testArray = [#[#{ #"language" :#"ESP"}, #{#"language" :#"ENG"},
#{#"language" :#"ENG"}, #{#"language" :#"FRH"}] mutableCopy];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"language != %#", #"ENG" ];
testArray = [[testArray filteredArrayUsingPredicate:predicate] mutableCopy];
I have just tested it, it works (it is short and nice to read, but NSPredicate can be really slow).
Another way to do it is using enumerateObjectsWithOptions:usingBlock:
[testArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSDictionary *dict, NSUInteger index, BOOL *stop) {
if ([dict[#"language"] isEqualToString:#"ENG"]) {
[testArray removeObjectAtIndex:index];
}
}];
Pleace notice that i use NSEnumerationReverse as NSEnumerationOptions because according to docs of removeObjectAtIndex:- Method :
To fill the gap, all elements beyond index are moved by subtracting 1
from their index.

Want to get key value from NSDictionary

I want to get all key values in an array. Here I used the keyword allKeysForObject. While using allKeysForObject, I got value within parenthesis. I want to store value without parenthesis.
Here is my code:
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"Hai" forKey:#"1"];
[dict setValue:#"lrd" forKey:#"2"];
NSArray *keys = [dict allKeys];
NSMutableArray *countryArray = [[NSMutableArray alloc]init];
NSMutableArray *keyObjects = [[NSMutableArray alloc]init];
for(NSString* key in keys) {
NSString *obj = [dict objectForKey:key];
[countryArray addObject:obj];
}
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [countryArray objectAtIndex:i]]];
}
NSLog(#"%#",[keyObjects objectAtIndex:0]);
The NSLog value is:
2013-11-28 17:12:48.400 Help[6775:c07] (
1
)
Thanks in advance.
Replace:
NSLog(#"%#",[keyObjects objectAtIndex:0]);
With:
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);
You are storing in keyObjects the value returned by allKeysForObject: which is a NSArray.
You will get all values in an NSDictionary using [dict allValues]. you dont need to manually iterate the array
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"Hai" forKey:#"1"];
[dict setValue:#"lrd" forKey:#"2"];
NSMutableArray *countryArray = [[dict allValues] mutableCopy];
NSMutableArray *keyObjects = [[NSMutableArray alloc]init];
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [countryArray objectAtIndex:i]]];
}
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);
Instead of using loop for getting all key values from NSDictionary use - (NSArray *)allKeys;
method to do that. It is always good to use given methods than writing our own code to achieve the same.
so replace of the for loop with following code...
keyObjects = [[dict allKeys]mutableCopy]; // mutableCopy because I think you want it mutable as your array is mutable.
EDIT
AFA your code concern, your are getting parenthesis because you are storing all keys in keyObjects array as array, that why you can see those parenthesis out there in you log statement. and this is because allKeysForObject method returns array of keys related to given object.
and if you want it to be done in your way here it is...
for (int i =0; i < [countryArray count]; i++) {
[keyObjects addObject:[dict allKeysForObject: [[countryArray objectAtIndex:i]0]]];
}
While NSLog-ing:
Whenever you see (...) it is array.
Whenever you see {...} it is dictionary.
So in your case it is shown as (1) so this is an array with one object.
Hence you need to do through one level down to retrieve it.
NSLog(#"%#",[[keyObjects objectAtIndex:0] objectAtIndex:0]); //or
NSLog(#"%#",[keyObjects objectAtIndex:0][0]);

Resources