views:

246

answers:

3

Hi,

I have a NSMutableArray that contains all the calendars on my system (as CalCalendar objects):

NSMutableArray *calendars = [[CalCalendarStore defaultCalendarStore] calendars];

I want to remove from calendars any CalCalendar objects whose title does not include the string @"work".

I've tried this:

for (CalCalendar *cal in calendars) {
    // Look to see if this calendar's title contains "work". If not - remove it
    if ([[cal title] rangeOfString:@"work"].location == NSNotFound) {
        [calendars removeObject:cal];
    }
}

The console is complaining that:

*** Collection <NSCFArray: 0x11660ccb0> was mutated while being enumerated.

And things go bad. Obviously it would seem you can't do what I want to do this way so can anyone suggest the best way to go about it?

Thanks,

+3  A: 

You can not change an array/list you are enumerating (in any language I know of). You will need to create a second list that you will add the calendars that you want to remove, to. Then iterate round the second list, removing the objects from the first. You can then dispose of the second list leaving just the original list with only the calendars you wish to keep hold of.

s1mm0t
+1  A: 

While you can not remove items in an array that you are using fast enumeration on, you have some options:

As markhunte noted, -calendars doesn't neccessarily return a mutable array - you'd have to use -mutableCopy to get a mutable array which you can filter:

NSMutableArray *calendars = [[[[CalCalendarStore defaultCalendarStore] 
                                calendars] mutableCopy] autorelease];

... or e.g. -filteredArrayUsingPredicate: for a immutable filtered copy.

NSArray *calendars = [[CalCalendarStore defaultCalendarStore] calendars];
calendars = [calendars filteredArrayUsingPredicate:myPredicate];
Georg Fritzsche
I went down the `-filterUsingPredicate:` method. Works fantastically and requires only two lines of code! Many thanks.
Garry
A: 

Hi, I noticed NSMutableArray will give the expected results from [[CalCalendarStore defaultCalendarStore] calendars]].

But the returned array from [[CalCalendarStore defaultCalendarStore] calendars]] is actually a NSArray and not an NSMutableArray. (also has a warning come up about expected structure)

This is all new to me so am I missing something here? or is this the correct way of going about this task..

NSMutableArray *workCals= [[NSMutableArray  alloc] initWithCapacity:2];
[workCals addObjectsFromArray: [[CalCalendarStore defaultCalendarStore] calendars]];


NSString *title = @"work";

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"title contains[c] %@",title ]; 
[workCals filterUsingPredicate:predicate];
NSLog(@"workCals %@",workCals );
[workCals release];

Cheers.

markhunte
You are right that `-calendars` does not neccessarily return mutable arrays - i updated my answer. In the future however please use comments (you can once you have got 50 reputation) or ask new questions instead of posting answers. SO is not a forum, its a QA site.
Georg Fritzsche
Thanks,But I was offering an answer.My question was more, is my answer correct, due to Objective-c being new to me. I will try to keep the comments and answers in the right places in future.
markhunte
Ah, it reads more like a question :) If you want a mutable copy simply use `-mutableCopy` as i pointed out in my answer.
Georg Fritzsche