Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dancks

macrumors regular
Original poster
Nov 8, 2009
100
0
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
 
Last edited:

fluxforge

macrumors member
Apr 16, 2010
35
0
europe
I was confused if NSMutableArray stored objects by copying or by reference

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.
 

ArtOfWarfare

macrumors G3
Nov 26, 2007
9,561
6,059
Click on the breakpoints tab of Xcode and turn on Exception breakpoints. That'll help you identify the line that's crashing your application.
 

dancks

macrumors regular
Original poster
Nov 8, 2009
100
0
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.

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)
 

dancks

macrumors regular
Original poster
Nov 8, 2009
100
0
Click on the breakpoints tab of Xcode and turn on Exception breakpoints. That'll help you identify the line that's crashing your application.

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.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.