Objective-C help with NSMutableArray

Discussion in 'Mac Programming' started by dancks, Apr 15, 2013.

  1. dancks, Apr 15, 2013
    Last edited: Apr 15, 2013

    macrumors member

    dancks

    Joined:
    Nov 8, 2009
    #1
    I am learning cocoa from 4th ed Cocoa Programming for Mac OS X. I am doing an where I make a simple gui that reads in user text and add it to a list: I'm using a NSTextField and NSTableView respectively. The problem is it crashes randomly, I cant get anything to show up in NSMutableArray so I guess I have a memory leak somewhere. I was confused if NSMutableArray stored objects by copying or by reference:

    GUI:

    Screen shot 2013-04-15 at 6.37.03 AM.png

    appdelegate.h:
    Code:
    #import <Cocoa/Cocoa.h>
    #import "NewTable.h"
    
    @interface AppDelegate : NSObject <NSApplicationDelegate,NSTableViewDelegate>
    {
        NSInteger at;
        int count;
        NSMutableArray *list;
    }
    
    @property (assign) IBOutlet NSWindow *window;
    
    @property (assign) IBOutlet NSTextField *input;
    @property (assign) IBOutlet NSButton *add;
    @property (assign) IBOutlet NSButton *remove;
    @property (assign) IBOutlet NSTableView *table;
    
    -(IBAction)addToList:(id)sender;
    -(IBAction)removeFromList:(id)sender;
    -(IBAction)checkList:(id)sender;
    
    @end
    
    appdelegate.m (GUI controller):
    Code:
    #import "AppDelegate.h"
    
    @implementation AppDelegate
    
    @synthesize window = _window;
    @synthesize add;
    @synthesize remove;
    @synthesize input;
    @synthesize table = _table;
    
    - (void)dealloc
    {
        [list release];
        [super dealloc];
    }
    -(id)init
    {
        [super init];
        at=0;
        count=1;
        list = [[NSMutableArray alloc] init];
        NSString *var = @"Type something";
        [list addObject:var];
        return self;
    }
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        // Insert code here to initialize your application
    }
    
    
    -(void)tableView:(NSTableView *)aTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
    {
        
    }
    - (int)numberOfRowsInTableView:(NSTableView *)tableView
    {
        NSLog(@"numberOfRowsInTableView called");
        return count;
    }
    - (id)tableView:(NSTableView *)tableView
    objectValueForTableColumn:(NSTableColumn *)tableColumn
                row:(int)row
    {
        NSLog(@"objectValueForTableColumn called");
        at = [_table clickedRow];
        if((int)at > count) at = (NSInteger) count;
        else if(at<0) at = 0;
        if(!count || (row>count))
        {
            return @"";
        }
        else
        {
            return [list objectAtIndex:row];
        }
    }
    
    
    
    -(void)tableViewSelectionDidChange:(NSNotification *)notification
    {
        NSInteger row = [_table selectedRow];
        if(row==-1)
        {
            return;
        }
        else
        {
            at = row;
        }
    }
    
    -(IBAction)addToList:(id)sender
    {
        NSLog(@"addToList click registered, at=%ld, count=%i",at,count);
        [list insertObject:[NSString stringWithString:[input stringValue]] atIndex:at];
        count++;
    }
    -(IBAction)removeFromList:(id)sender
    {
        NSLog(@"removeFromList click registered at=%ld, count=%i",at,count);
        if(at<count)
        {
            NSString *var = [list objectAtIndex:at];
            [list removeObjectAtIndex:at];
            [var release];
            count--;
        }
    }
    
    -(IBAction)checkList:(id)sender
    {
        NSString *the_list = [[NSString alloc] initWithString:@"List: "];
        for (NSString *var in list)
        {
            [the_list stringByAppendingFormat:@"%@, %@",the_list,var];
        }
        NSLog(the_list);
        [the_list release];
    }
    
    -(void)awakeFromNib
    {
        NSIndexSet *indices = [NSIndexSet indexSetWithIndex:1];
        [_table selectRowIndexes:indices byExtendingSelection:NO];
        [_table scrollRowToVisible:1];
        at = count;
    }
    @end
    
     
  2. macrumors member

    Joined:
    Apr 16, 2010
    Location:
    europe
    #2
    It stores the reference and retains it.

    Oh, and about your code: Don't call directly -dealloc on objects. It's not intended to be called from the outside and will lead to undefined behaviour. Dealloc will be called automatically when the object gets destroyed. (The exception is the [super dealloc] call which is ok.)

    If you're working without ARC you should call -release where you put your dealloc calls in the example. With ARC everything is taken care for you by the runtime.
     
  3. macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #3
    Click on the breakpoints tab of Xcode and turn on Exception breakpoints. That'll help you identify the line that's crashing your application.
     
  4. thread starter macrumors member

    dancks

    Joined:
    Nov 8, 2009
    #4
    That is what I figured, so I make NSString pointers, pass them in, and let the variables fall out of scope without worry of a memory leak, and simply release when I need them gone. But with all that why is NSMutableArray losing scope of the strings and causing segfaults? I thought the above code was correct (other than the dealloc/release thing)
     
  5. dancks, Apr 15, 2013
    Last edited: Apr 15, 2013

    thread starter macrumors member

    dancks

    Joined:
    Nov 8, 2009
    #5
    It automatically compiles with the GDB flag so XCode knows which line it crashed on. Last time it ran (It crashes in different places) I crashed on
    Code:
    for(NSString *var in list)
    and here:
    Code:
    [list insertObject:[NSString stringWithString:[input stringValue]] atIndex:at];
    Which would make sense if its pointing to bad memory.
     

Share This Page