Tabs

Discussion in 'Mac Programming' started by titaniumdecoy, Dec 18, 2007.

  1. titaniumdecoy macrumors member

    Joined:
    Oct 13, 2005
    #1
    Hi all,

    I am using PSMTabBarControl in a project, but it is giving me some headaches. When I remove a tab (actually, any tab but the rightmost) from the NSTabView it is controlling, I get this error:

    2007-12-18 13:48:45.753 MyApp[743:10b] *** Collection <NSCFArray: 0x13a0e0> was mutated while being enumerated.

    In the demo project that comes with PSMTabBarControl, this error does not occur when removing any tab. Yet I know this error occurs when I remove a tab (which is not the rightmost tab) because when I execute the following:

    Code:
    NSLog(@"will remove tab");
    [tabView removeTabViewItem:tabViewItem];
    NSLog(@"did remove tab");
    "did remove tab" is never printed.

    Any thoughts? Thanks.
     
  2. antibact1 macrumors 6502

    Joined:
    Jun 1, 2006
    #2
    Has the retain count for the tab dropped to 0? You can't send messages to released object or trouble will ensue.
     
  3. titaniumdecoy thread starter macrumors member

    Joined:
    Oct 13, 2005
    #3
    I tried this:

    Code:
    NSLog(@"will remove tab");
    [tabViewItem retain];
    [tabView removeTabViewItem:tabViewItem];
    NSLog(@"did remove tab");
    But unfortunately it makes no difference. As far as I can tell it is not released before that either.

    Is there any way to get this error without using an NSEnumerator?
     
  4. Eraserhead macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
    #4
    I add and remove tabViewItem's fine from an NSTabView I use:
    Code:
    	NSTabViewItem *tabViewItem=[[[NSTabViewItem alloc] init] autorelease];
    	[tabView addTabViewItem:tabViewItem];
    
    to add and

    Code:
    [tabView removeTabViewItem:[tabView tabViewItemAtIndex:0]];
    
    to remove
     
  5. titaniumdecoy thread starter macrumors member

    Joined:
    Oct 13, 2005
    #5
    Thanks, Eraserhead. I think the problem has to do with the PSMTabBarControl that is attached to the NSTabView. The problem is, I looked through the code for the control (as it is open source) and was unable to find any instance of an item being removed from an array while it was being enumerated. I find this very puzzling.
     
  6. titaniumdecoy thread starter macrumors member

    Joined:
    Oct 13, 2005
    #6
    The problem was with PSMTabBarControl, as I suspected. Here is an excerpt from PSMTabBarControl.m:

    Code:
    - (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView
    {
        NSArray *tabItems = [tabView tabViewItems];
        // go through cells, remove any whose representedObjects are not in [tabView tabViewItems]
        NSEnumerator *e = [_cells objectEnumerator];
        PSMTabBarCell *cell;
        while(cell = [e nextObject]){
            if(![tabItems containsObject:[cell representedObject]]){
                [self removeTabForCell:cell];
            }
        }
    _cells is being mutated while it is being enumerated (the call to removeTabForCell: calls removeObject: on cell). I fixed it by enumerating over a copy of the _cells array:

    Code:
    NSEnumerator *e = [[[_cells copy] autorelease] objectEnumerator];
     
  7. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    Interesting, I use PSMTabBarControl in a project but haven't come across this error in it, although it seems new to Leopard since 10.4 never produced it. I guess Apple is getting stricter :)
     
  8. titaniumdecoy thread starter macrumors member

    Joined:
    Oct 13, 2005
    #8
    I e-mailed the developer about the problem and he already wrote back to say that he will fix it. :cool:
     
  9. Krevnik macrumors 68030

    Krevnik

    Joined:
    Sep 8, 2003
    #9
    One thing to mention, is that when an exception is thrown, the stack unravels until something catches the exception. When you get a message like that in the run log, there was an exception that the event loop caught since you didn't. But it also means that any code after the exception was thrown isn't executed.

    Hopefully this information might help debugging issues in the future. :)
     

Share This Page