I have array of custom objects. I am removing objects from that array but I am not able to remove the objects from that array here is my code.
if([arr_userFav count]>0)
{
int i;
for (i=0; i<[arr_userFav count]; i++)
{
Post *objectCopy = [arr_userFav copy]; //create a copy of our object
[arr_temp_Fav addObject: objectCopy];
}
NSLog(#"size of arr_temp_Fav %lu",(unsigned long)[arr_temp_Fav count]);
[arr_userFav removeAllObjects];
}
after removing objects form arr_userFav I have size of array as zero but when I put a breakpoint after it & see the objects in it then I don't get a empty array. Please tell how to do it?
Below is the screenshot
Please look very carefully at what your code is doing.
The object that you add to arr_temp_fav is a copy of arr_user_fav, that is a copy of the complete array. So if your array originally had ten elements, you now have an array with ten arrays as elements, each with ten elements itself. If you had 10,000 elements it's a lot worse.
Post *objectCopy = [arr_userFav copy]; //create a copy of our object
Here we have a case of a comment that would be completely pointless if it was correct - it is however incorrect and may be hiding from you what you are doing wrong.
Related
This question already has answers here:
Removing object from NSMutableArray
(5 answers)
Closed 7 years ago.
My program has a NSMutable Array named as "matchedCards", and I have added few object in it of type Card, now I need to remove the objects from the array, and I use the following code for it:
for (Card * removeCards in matchedCards)
{
[self.matchedCards removeObject:removeCards];
}
The first card-object gets removed , and after that the program gets crashed , Can anyone explain the reason behind it, if it successfully removes the first object, why it starts throwing error from 2nd object onwards
You can't remove elements from an array while fast-enumerating it.
If you simply want to remove all objects do
[self.matchedCards removeAllObjects];
If you want to remove only certain elements however, remember their indices in an IndexSet and remove those
NSMutableIndexSet* indexesToRemove = [NSMutableIndexSet new];
for (NSUInteger index = 0; index < [self.matchedCards count]; ++index) {
if (whatever) {
[indexesToRemove addObject:index];
}
}
[self.matchedCards removeObjectsAtIndexes:indexesToRemove];
You can't remove an object from an array while iterating on it. Do this instead:
for (Card * removeCards in [matchedCards copy])
{
[self.matchedCards removeObject:removeCards];
}
Read the crash log. It will say something along the lines of...
"Collection was stated while being enumerated"
Or something like that.
You can't mutate an array while iterating over it using a for:in loop.
You can do this though...
[matchedCards enumerateObjectsUsingBlock:^(Card *removedCards, NSInteger idx, BOOL *stop) {
[self.matchedCards removeObject:card];
}];
Also, with your current code you are actually removing all of the objects from the matchedCards array. It will result in an empty array. Are you sure that's what you want?
The reason is because you are removing the current object and ruin the for-statement
Here's a solution:
for (int i = 0; i < self.matchedCards.count; i++)
{
if ([self.matchedCards[i] isKindOfClass:[YourClass class]])
{
[self.matchedCards removeObject:self.matchedCards[i]];
i--; // invalidate the removed index
}
}
NSLog(#"%#", self.matchedCards);
Take note that i-- is important, else you will not get through to the last element of the array..
Hope this helps you.. Cheers..
// if remove all objects
[matchedCards removeAllObjects];
// if you want to remove using index
for (int i =[matchedCards count]-1; i>=0; i++) {
if (condition) {
[matchedCards removeObjectAtIndex:i];
}
}
I am trying to check if the NSMutableArray has a specific object, before adding the object to it, if exists then don't add.
i looked over many posts explaining how to do this, managed to implement it like this, but it always gives me that the object "doesn't exist", though i already added it !
//get row details into FieldLables Object
AllItemsFieldNames *FieldLabels = feedItems[row];
// object to hold single row detailes
AllItemsFieldNames *SelectedRowDetails = [[AllItemsFieldNames alloc] init];
SelectedRowDetails.item_name = FieldLabels.item_name;
//SelectedRowDetails.item_img = FieldLabels.item_img;
SelectedRowDetails.item_price = FieldLabels.item_price;
//NSLog(#"item has been added %#", SelectedRowDetails.item_name);
//NSLog(#"shopcartLength %lu", (unsigned long)SelectedFieldsNames.count);
if([SelectedFieldsNames containsObject:SelectedRowDetails])
{
NSLog(#"Already Exists!");
}
else
{
NSLog(#"Doesn't Exist!");
[SelectedFieldsNames addObject:SelectedRowDetails];
}
I can display all object from the NSMutableArray into a table, what i need to do in the above code is stop the addition of duplicate objects.
The first method listed on the NSArray documentation under the section "querying an array" is containsObject:. If it's not working, that suggests that your implementation of isEqual: is not correct. Make sure you follow the note in the documentation:
If two objects are equal, they must have the same hash value. This
last point is particularly important if you define isEqual: in a
subclass and intend to put instances of that subclass into a
collection. Make sure you also define hash in your subclass.
You might also consider using an NSSet since you can't add duplicates to that. Of course, this would also require a working version of isEqual:.
Sets are composed of unique elements, so this serves as a convenient way to remove all duplicates in an array.
here some sample,
NSMutableArray*array=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4", nil];
[array addObject:#"4"];
NSMutableSet*chk=[[NSMutableSet alloc ]initWithArray:array]; //finally initialize NSMutableArray to NSMutableSet
array= [[NSMutableArray alloc] initWithArray:[[chk allObjects] sortedArrayUsingSelector:#selector(compare:)]]; //after assign NSMutableSet to your NSMutableArray and sort your array,because sets are unordered.
NSLog(#"%#",array);//1,2,3,4
This question already has answers here:
Random number without repeating
(3 answers)
Closed 8 years ago.
I'm brand new to SpriteKit, and I'm creating a game that involves randomizing the CGPoint positions of objects on my screen when the user reaches certain score increments. I created a plist of the 8 set positions I want my objects to choose from when this method is called, but I'm having a problem with my objects selecting duplicate plist positions and overlapping each other. Is there a method I can call that will prevent my objects from picking the same position from the plist as another object when that method is called?
FYI, I plan on calling this randomization method many times throughout the course of the game.
I wrote the following code but my game crashes.
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
list = [_objectList copy];
NSInteger randomIndex = arc4random()%list.count;
Objects *object = [list objectAtIndex:randomIndex];
[list addObject:object];
[list removeObject:object];
return list;
}
Your method has several problems. First, you're passing in a mutable array called list, but then in the first line of the method you redefine what list is. You either shouldn't pass in the list to start with, or you shouldn't redefine it. Second, if _objectList is an immutable array, you need to use mutableCopy to make it a mutable array, not copy. Third, there's no need to add an object to the list, and then turn around and remove it in the next line. Also a better random number function to use is arc4random_uniform(). So, if you're passing in a mutable array, your method should be,
- (NSMutableArray *)pickAndRemoveFromList:(NSMutableArray *)list {
NSInteger randomIndex = arc4random_uniform((int)list.count);
Objects *object = [list objectAtIndex:randomIndex];
[list removeObject:object];
return list;
}
My problem is when I copy an array with objects, it seems that if i change the copied array, the original array changes as well. Below is a simplified version of my code.
I have an array of objects
#interface TimesViewController (){
NSMutableArray *route1;
}
I fill these objects up in my ViewDidLoad method
route1 = [[NSMutableArray alloc] init];
while (sqlite3_step(statement) == SQLITE_ROW) {
StopsOnRoutes *stopOnRoutes = [[StopsOnRoutes alloc] init];
[stopOnRoutes setStart_time:p_time];
[stopOnRoutes setStart_route_id:p_route];
[stopOnRoutes setStart_stop_id:p_stop];
[stopOnRoutes setStop_time:c_time];
[stopOnRoutes setStop_route_id:c_route];
[stopOnRoutes setStop_stop_id:c_stop];
[stopOnRoutes calc];
[route1 addObject:stopOnRoutes];
}
BUT when I try to copy route1 and make a few changes, they change both in route1 and amTimes
NSMutableArray *amTimes = [[NSMutableArray alloc] init];
[amTimes addObjectsFromArray:route1];
for(int i = 0; i<amTimes.count; i++){
[[amTimes objectAtIndex:i] setStop_time:[[amTimes objectAtIndex:i] stop_time]-86400];
[[amTimes objectAtIndex:i] setStart_time:[[amTimes objectAtIndex:i] start_time]-86400];
}
How can I copy route1 to amTimes, so if I change an object in AM times, it won't change in route1.
The way arrays work they simply hold references (pointers) to the objects in the array. Therefore when you add objects, it does not create a new object and point to it, it simply points to that very same object. What you want to do is referred to as a deep copy array, which involves coping each object inside the array.
Which is what happens when you use
- (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag
Each object in the array is send a copyWithZone, you can implement copyWithZone in each of the objects you want to add to your array, and then do
[myArray addObject[myObject copy]];
Or you can also use
[[NSArray alloc] initWithArray:otherArray copyItems:YES] //You need to implement copyWithZone in the items you want to copy.
This will give you the result that you want.
You need to have your StopOnRoutes class implement the NSCopying protocol and the copyWithZone: method. This method needs to create a copy of self.
Then you can do this:
NSMutableArray *amTimes = [[NSMutableArray alloc] init];
for (StopOnRoutes *obj in route1) {
[amTimes addObject:[obj copy]];
}
Container objects don't contain copies of the objects that are added to them, they contain pointers to the objects. If you add the same object to 2 arrays, it is a member of both arrays.
If you want to create an array of copies, you need to do several things:
You need to implement the NSCopying protocol for the objects in your array so you can copy them.
Then you'd need to create a new mutable array with room for the same number of elements as the first array, loop through the first array, copy each item, and add it to the second array.
If your array contains only standard system objects that support NSCopying then your work is simpler. If your array contains different kinds of custom objects or complex custom objects then you might have more work to do.
Try using setArray: i.e.[amTimes setArray:route1];
I have an array that has different data, one being temperature recorded in celcius. when a user changes the default setting to fahrenheit i need to change the array of information when it displays in a collectionView. the program compiles properly, but when the view loads the compiler crashes with no error and just highlights the line in green and say in right corner Thread 1: breakpoint1.1
The line highlighted is bellow
[dict setObject:[NSNumber numberWithInteger:number] forKey:#"temp"];
i have also just tried with no success just to bypass the problem:
[dict setObject:#"11" forKey:#"temp"];
my code for looping through the array and changing the data is:
changedArray = [[NSMutableArray alloc] initWithCapacity:50];
for (NSMutableDictionary *dict in locationArray) {
if ( [[dict objectForKey:#"site"] isEqual:[defaults objectForKey:#"location"]] ) {
NSInteger number = [[dict objectForKey:#"temp"] integerValue];
number = ((number * 1.8) + 32);
[dict setObject:[NSNumber numberWithInteger:number] forKey:#"temp"];
[changedArray addObject:dict];
}
}
If i remove the three lines of code changing the temperature value in the dict, it compiles and run correctly. Any inside for this ios noob would be great thanks. :-)
I guess the dictionary instances in your array are all immutable NSDictionary object. Just type casting won't turn them to mutable ones. Try the following
Iterate through Array
Find the correct dictionary
Form a mutable NSMutableDictionary
Edit the mutable one
Update back to the array (The array also needs to be a mutable one)
But my advice would be to keep the temperate in only one unit always, the unit which the users tend to use more. Only when you need to display it, check with the user chosen unit do the calculation and refresh it.