From an exercise in a cocoa programming book I'm trying to make a to do list app that simply adds, removes and change the entries in the table. I have a lot of things wrong with it.

relevant info:

  • add button: add entry with text from text field. If an entry is highlighted in the table the text is supposed to replace that entry, and it works.
  • remove: remove an entry. Shouldn't do anything unless a field is highlighted. Only removes the first entry.
  • int at: the selected row number, for add and remove button functionality.
  • check number: a debug attempt where I can enter a number and "at" is supposed to change to that number
  • label at the bottom: Supposed to update and display "at" when I click add, remove or click a row. only works when I click add button

GUI:

797ec1ce477b788b0bb35ed1548bedb9

app delegate code:
.h:

#import <stdlib.h>
#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate,NSTableViewDelegate>
{
    int count, at;
    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;
@property (assign) IBOutlet NSTextField *setNum;
@property (assign) IBOutlet NSTextField *label;


-(IBAction)addToList:(id)sender;
-(IBAction)removeFromList:(id)sender;
-(IBAction)setAt:(id)sender;
-(int)converttonum:(const char *)a;
-(NSString *)converttonsstring:(int)a;

@end

.m:

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize add;
@synthesize remove;
@synthesize input;
@synthesize table = _table;
@synthesize setNum;
@synthesize label = _label;

- (void)dealloc
{
    [list release];
    [super dealloc];
}
-(id)init
{
    NSLog(@"Init called");
    self = [super init];
    at=0;
    count=0;
    list = [[NSMutableArray alloc] init];
    [[NSNotificationCenter defaultCenter] 
     addObserver:self selector:@selector(tableViewSelectionDidChange:) 
     name:@"NSTableViewSelectionDidChangeNotification" object:_table];
    [_label setStringValue:@"OK good to go"];
    return self;
}
- (int)numberOfRowsInTableView:(NSTableView *)tableView
{
    return count;
}
- (id)tableView:(NSTableView *)tableView
objectValueForTableColumn:(NSTableColumn *)tableColumn
            row:(int)row
{
    return [list objectAtIndex:row];
}
-(void)tableViewSelectionDidChange:(NSNotification *)notification
{
    NSInteger row = [_table selectedRow];
    if(row==-1)
    {
        at=count+1;
    }
    else
    {
        at = (int)row;
    }
    [_label setStringValue:[self converttonsstring:at]];
}
- (IBAction)tableViewSelected:(id)sender
{
    at = (int)[sender selectedRow]-1;
    NSLog(@"the user just clicked on row %d", at);
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)addToList:(id)sender
{
    [_label setStringValue:[self converttonsstring:at]];
    if((at>count)||(!count))
    {
        count++;
        [list addObject:[NSString stringWithString:[input stringValue]]];
    }
    else
    {
        [list replaceObjectAtIndex:at withObject:[NSString stringWithString:[input stringValue]]];
    }
    at=count+1;
    [_table reloadData];
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)removeFromList:(id)sender
{
    [_label setStringValue:[self converttonsstring:at]];
    if(at<count)
    {
        [list removeObjectAtIndex:at];
    }
    [_table reloadData];
    at=count+1;
    count--;
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)setAt:(id)sender
{
    int num = [self converttonum:[[input stringValue] UTF8String]];
    at=num;
    [_label setStringValue:[self converttonsstring:at]];
}
-(int)converttonum:(const char *)a
{
    int num=0;
    for(const char * b = a;*b;b++)
    {
        //int i = (((*b)-'0')>0)?((*b)-'0'):0;
        int i = (int)((((*b)-'0')>0)?((*b)-'0'):0);
        i = (i<10)?i:0;
        num = (num*10)+i;
    }
    return num;
}
-(NSString *)converttonsstring:(int)a
{
    int size=(a & 96)?4:3;
    char *b = malloc(sizeof(size));
    char *d=b;
    b[--size]='\0';
    int c;
    for(c=a;(c>0)&&(size>=0);c/=10)
    {
        b[--size] = (char)((c%10)+48);
    }
    return [[NSString alloc] initWithUTF8String:d];
}
-(void)awakeFromNib
{
    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:1];
    [_table selectRowIndexes:indices byExtendingSelection:NO];
    [_table scrollRowToVisible:1];
    at = 0;
}
@end

and I uploaded a zip file of my project in case you need to check out the bindings or connections or something. I appreciate any help.

So I have most everything working now except the remove from list feature. So, remove button activates removeFromList method, which looks like:

-(IBAction)removeFromList:(id)sender
{
    NSLog(@"count: %d, at: %d\n",count,at);
    /*if(at<count)
    {
        [list removeObjectAtIndex:at];
    }
    [_table reloadData];
    at=count+1;
    count--;
    [_label setStringValue:[self converttonsstring:at]];*/
}

With just the NSLog, it prints what I expect, int is never higher than 1 less than the count. Something I can't figure out is with the rest of the code is when I click the remove button it gets stuck in the pressed position as the program enters an infinite loop, and prints out:

2013-05-04 02:32:17.874 ToDoList[571:903] count: 7, at: 2
2013-05-04 02:32:34.763 ToDoList[571:903] *** -[NSCFArray objectAtIndex:]: index (6) beyond bounds (6)
**last line repeats on and on**

The bounds, from what I can tell is technically in bound, on that run I had 7 members in NSMutableArray so index 6 should point to the last position. Even though int at=2.

so other than writing my own version of NSMutableArray, how would I do this?

updated appdelegate.m:

//http://cocoadev.com/wiki/NSTableViewTutorial
//
//  AppDelegate.m
//  ToDoList
//
//  Created by Jason Dancks on 4/13/13.
//  Copyright (c) 2013 SUNY OCC. All rights reserved.
//

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize add;
@synthesize remove;
@synthesize input;
@synthesize table = _table;
@synthesize setNum;
@synthesize label = _label;

- (void)dealloc
{
    [list release];
    [super dealloc];
}
-(id)init
{
    NSLog(@"Init called");
    self = [super init];
    at=0;
    count=0;
    list = [[NSMutableArray alloc] init];
    [[NSNotificationCenter defaultCenter] 
     addObserver:self selector:@selector(tableViewSelectionDidChange:) 
     name:@"NSTableViewSelectionDidChangeNotification" object:_table];
    [_label setStringValue:@"OK good to go"];
    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
{
    return count;
}
- (id)tableView:(NSTableView *)tableView
objectValueForTableColumn:(NSTableColumn *)tableColumn
            row:(int)row
{
    /*if(count && (row<count))
    {
        return [list objectAtIndex:row];
    }*/
    return [list objectAtIndex:row];
}
-(void)tableViewSelectionDidChange:(NSNotification *)notification
{
    NSInteger row = [_table selectedRow];
    if(row==-1)
    {
        at=count+1;
    }
    else
    {
        at = (int)row;
    }
    [_label setStringValue:[self converttonsstring:at]];
}
- (IBAction)tableViewSelected:(id)sender
{
    /*at = (int)[sender selectedRow]-1;
    NSLog(@"the user just clicked on row %d", at);
    [_label setStringValue:[self converttonsstring:at]];*/
    NSInteger row = [_table selectedRow];
    if(row==-1)
    {
        at=count+1;
    }
    else
    {
        at = (int)row;
    }
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)addToList:(id)sender
{
    [_label setStringValue:[self converttonsstring:at]];
    if((at>count)||(!count))
    {
        count++;
        //[list insertObject:[NSString stringWithString:[input stringValue]] atIndex:at];
        [list addObject:[NSString stringWithString:[input stringValue]]];
    }
    else
    {
        [list replaceObjectAtIndex:at withObject:[NSString stringWithString:[input stringValue]]];
    }
    //[list insertObject:[NSString stringWithString:[input stringValue]] atIndex:at];
    at=count+1;
    [_table reloadData];
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)removeFromList:(id)sender
{
    //[_label setStringValue:[self converttonsstring:at]];
    NSLog(@"count: %d, at: %d\n",count,at);
    if(at<count)
    {
        [list removeObjectAtIndex:at];
    }
    [_table reloadData];
    at=count+1;
    count--;
    [_label setStringValue:[self converttonsstring:at]];
}
-(IBAction)setAt:(id)sender
{
    int num = [self converttonum:[[setNum stringValue] UTF8String]];
    NSLog(@"In setAt: original string: %s, converted to: %d\n",[[setNum stringValue] UTF8String],num);
    at=num;
    [_label setStringValue:[self converttonsstring:at]];
}
-(int)converttonum:(char *)a
{
    int num=0;
    char * b;
    for(b = a;*b;b++)
    {
        int i = (int)((((*b)-'0')>0)?((*b)-'0'):0);
        i = (i<10)?i:0;
        num = (num*10)+i;
    }
    return num;
}
-(NSString *)converttonsstring:(int)a
{
    int size=(a & 96)?4:3;
    char *b = malloc(sizeof(size));
    char *d=b;
    //b+=size-1;
    b[--size]='\0';
    int c;
    for(c=a;(c>0)&&(size>=0);c/=10)
    {
        b[--size] = (char)((c%10)+48);
    }
    if (strncmp(d,"",size)==0) d="0";
    return [[NSString alloc] initWithUTF8String:d];
}
/*-(NSString *)converttonsstring:(int)a
{
    int size=1+((a/10)-1);
    char *b = malloc(sizeof(size));
    b+=size-1;
    int c;
    for(c=a;c>0;c/=10)
    {
        *b-- = (char)((c%10)+48);
    }
    return [[NSString alloc] initWithUTF8String:b];
}*/
-(void)awakeFromNib
{
    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:1];
    [_table selectRowIndexes:indices byExtendingSelection:NO];
    [_table scrollRowToVisible:1];
    at = 0;
}
@end
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.