removeObject in ios [duplicate] - ios

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];
}
}

Related

Unable to remove all custom objects from array in Objective-C?

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.

Adding only a certain number of the same object to an array?

I am working on a project where I am adding objects to an array when the user taps the object in my UITableView. The user can add multiples of a single object, but no more than 4. I can't figure out how to stop the object from being added if there are already 4 in the array. Is there a way to check how many of a single object are stored in the array?
Here's what I have so far:
if (![deckArray containsObject:[cardArray objectAtIndex: indexPath.row]] || [deckArray containsObject:[cardArray objectAtIndex: indexPath.row]] ) {
[deckArray addObject:[cardArray objectAtIndex: indexPath.row]];
}
First, your conditional statement is always true. It says: "if the deck does or does not contain the object then add it."
Here is an inefficient way to do this is. It is slow because you need to enumerate every card in the deckArray, but if that array will never be very large (say 100 elements), then this is good enough:
id card = [cardArray objectAtIndex:indexPath.row];
int count = 0;
for( id deckCard in deckArray )
{
if( [deckCard isEqualTo:card] )
count++;
}
if( count < 4 )
[deckArray addObject:card];
If the order of deckArray does not matter, you could use NSCountedSet and have a very quick way to check how many times you've added the card:
// somewhere else, deck is declared as:
NSCountedSet * deck = [NSCountedSet set];
// somewhere else
id card = [cardArray objectAtIndex:indexPath.row];
if( [deck countForObject:card] < 4 )
[deck addObject:card];

Insert every other object from one NSMutableArray into another NSMutableArray

I'm trying to add every other object from one NSMutableArray to another.
Here is my code so far.
for (int i = 0; i < all.count; i ++) {
[cat insertObject:all atIndex:0];
[all removeObjectAtIndex:i];
}
It did not add anything from the mutableArray called all, to the mutableArray called cat.
I would like to remove all even objects from one array and put it to the next to the next.
You are inserting the array all into cat. You should be taking all's element instead, like this:
for (int i = 0; i < all.count; i += 2) {
[cat addObject:[all objectAtIndex:i]];
}
or use the square bracket syntax for accessing array elements of all, like this:
for (int i = 0; i < all.count; i += 2) {
[cat addObject:all[i]];
}
First of all you need to be sure that your cat object has been previously initialized with an empty NSMutableArray.
Then the code for passing every other object from one to another could look like:
for (int i = 0; i < [all count]; i++) {
id item = [all objectAtIndex:i];
[cat addObject:item];
[all removeObject:item];
}
This would iterate from 0 to all.count, add the object at an index to the cat array and delete it from the all array. You don't need to iterate with i += 2 because the way the removeObject works, it shifts the indexes of the remaining objects to fill the space of the object removed.
Let's say you removed the index 0, then the index 1 will be the new index 0, so for you to go to your original index 2 you will only need to go to your new index 1.
You can initialize the cat array in one shot like this
NSArray* cat =[NSArray arrayWithArray:all];

NSMutableArray Allocate then replaceObjectAtIndex

I have a NSMutableArray that i define in the header file as:
#property (strong, nonatomic) NSMutableArray *tempPhotosArray;
Then i allocate as:
_tempPhotosArray = [[NSMutableArray alloc] init];
What i'd like to know is if i then go to replaceObjectAtIndex the program will complain on an out of bounds. I want to keep only a set number of items in that array, so is it possible to do a insert or replace? i.e. if at index 0 it is empty do an insert, if there is an object already replace it?
Thanks
i think i agree with Hani Ibrahim. Since you said you only want to keep a set number of objects in the array. So how many you want?
// add these code when you initialize the array
int aSetNumber = 5;
_tempPhotosArray = [[NSMutableArray alloc] init];
for (int i = 0; i < aSetNumber; i++)
{
[_tempPhotosArray addobject: [NSNull null]];
}
i guess then you can do whatever you want, i don't know what exactly you want to do in this case, but i would check if the object in that position is NSNUll, if so, replace that, if not, i don't know what you want them
//use these code when you trying to insert the real object
if([[_tempPhotoArray objectAtIndex:anIndex] isKindOfClass: [NSNull class]])
{
//replace it here
}
As to why you are getting an error, what everyone else wrote is accurate, but....
The description of what you want doesn't match what an NSArray is. It sounds like you want a list of up to 5 items and never more than 5. It might be that if you try to add a 6th item the "oldest" goes away. Like a "recently opened" file history. You can make this type of functionality with an NSArray, but that's not what it is out of the box.
I would suggest making your own object class. I'm not going to write all the code for you, because this sounds suspiciously like programming homework, but I will point you in the correct direction.
FivePack <-- our class
NSArray *storage; <-- where we house the data
// a public method which lets you add things.
- (void)addItem:(id)item {
int indexOfLastItemInArrayToSave = 4;
if (storage.length < 4)
indexOfLastItemInArrayToSave = length-1;
NSRange range = NSMakeRange(0, indexOfLastItemInArrayToSave);
NSArray *temp = [storage subArrayWithRange:range];
// now create a new array with the first item being "item" that
// was passed in and the rest of the array being the contents of temp.
// Then save that to storage.
}
What you want to do with the data and writing something to get it from your new object is up to you, because I'm not sure how you want to do it.
There are no objects in the array when you initially created it, so there is nothing to replace.
Like this?
if([_tempPhotosArray count] > 0)
//replace object
else
//add object to array

iOS: get 3 different random elements from an NSMutableArray

I have a NSMutableArray of N Integer elements (N>4), I want to get 3 different random elements from this array. I do not really need a perfectly-uniform distribution, just 3 different random elements should be OK. Do you have any suggestion? Thanks
Make NSIndexSet, and keep adding
int value = arc4random() % array.count;
items to it until its size gets to 3. The you know that you have your three indexes.
NSMutableIndexSet *picks = [NSMutableIndexSet indexSet];
do {
[picks addIndex:arc4random() % array.count];
} while (picks.count != 3);
[picks enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSLog(#"Element at index %ud: %#", idx, [array elementAt:idx]);
}];
for (int i = 1; i <= 3; i++) {
int index = (int)(arc4random() % [array count]);
id object = [array objectAtIndex:index];
[array removeObjectAtIndex:index];
}
arc4random() returns a random number in the range [0,2^32-1). The remainder when you take the modulus with the size of the array gets you a value between [0,arrayCountLessOne].
If you don't want to change your original data array, you can just make a copy of the array.
If you want to do this more than once from various places in your code then consider doing this: The "Objective C way" is to create a category on NSMutableArray which adds a method randomObjects. The method itself should generate three random integers from 0 to the length of the array -1 (N-1), then return a set of objects from the array at those indices, as per the other answers here (dasblinkenlight's in particular.)
First, create the category. Create a new header file NSMutableArray+RandomObject.h, containing:
#interface NSMutableArray (RandomObjects)
- (NSSet *) randomObjects;
#end
The RandomElement in parentheses is the name of your category. Any class you write that includes this new header file will give all your NSMutableArray instances the randomElement method.
Then the implementation, in NSMutableArray+RandomObjects.m:
#implementation NSMutableArray (RandomObjects)
- (NSSet *) randomObjects {
// Use the code from #dasblinkenlight's answer here, adding the following line:
return picks;
}
#end
And that's basically it. You've effectively added that capability to NSMutableArray.
Nice answer from dasblinkenlight!
In Swift 4:
let indexes = NSMutableIndexSet()
if array.count > setSize {
repeat {
indexes.add(Int(arc4random_uniform(UInt32(array.count))))
} while (indexes.count < setSize)
}

Resources