Adding Row code not executing


#1

Copied code in the book, run in in the iOS 6.0 Simulator and when I press the new button, there is no response.

AppDelegate.h

[code]#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder

@property (strong, nonatomic) UIWindow *window;

@end
[/code]

AppDelegate.m

[code]#import “AppDelegate.h”
#import “ItemsViewController.h”

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    //create and itemsViewController

    ItemsViewController *itemsViewController = [[ItemsViewController alloc] init];

    // place itemsViewController’s table view in the window hierarchy

    [[self window] setRootViewController:itemsViewController];

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
    }
    [/code]

BNRItemStore.h

[code]#import <Foundation/Foundation.h>

@class BNRItem;

@interface BNRItemStore : NSObject

{

NSMutableArray *allItems;

}

+(BNRItemStore *)sharedStore;

-(NSArray *)allItems;
-(BNRItem *)createItem;

@end
[/code]

BNRItemStore.m

[code]#import “BNRItemStore.h”
#import “BNRItem.h”

@implementation BNRItemStore

+(BNRItemStore *)sharedStore
{

// create a static variable, static variables don't get destroyed

static BNRItemStore *sharedStore = nil;

if (!sharedStore)
    
    
    // jump to super's implementation of allocwithZone to avoid the call loop
    
    sharedStore = [[super allocWithZone:nil] init];
    
    return sharedStore;

}

+(id)allocWithZone:(NSZone *)zone
{

return [self sharedStore];

}

-(id)init
{

self = [super init];

if(self) {
    
    
    allItems = [[NSMutableArray alloc] init];
    
}

return self;

}

//implement the allItems and createItems methods

-(NSArray *)allItems
{

return allItems;

}

-(BNRItem *)createItem
{

BNRItem *p = [BNRItem randomItem];

[allItems addObject:p];

return p;

}

@end
[/code]

ItemViewController.h

#import <Foundation/Foundation.h>
#import "BNRItemStore.h"
#import "BNRItem.h"

@interface ItemsViewController : UITableViewController


{
    
    IBOutlet UIView *headerView;
    
}


-(UIView *)headerView;
-(IBAction)addNewItem:(id)sender;
-(IBAction)toggleEditMode:(id)sender;

itemViewController.m

#import "ItemsViewController.h"
#import "BNRItemStore.h"
#import "BNRItem.h"
@implementation ItemsViewController






-(id)init{
    
    
    self = [super initWithStyle:UITableViewStyleGrouped];
    
    if(self)
    {
     
        for (int i =0; i< 20; i++) {
            [[BNRItemStore sharedStore] createItem];
        }
        
    }
    return self;
}


-(id)initWithStyle:(UITableViewStyle)style
{
    
    return [self init];
    
}


// implement the required methods implemented to be tableView data source

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    
    return [[[BNRItemStore sharedStore] allItems] count];
    
    
}



-(UIView *)headerView
{
    
    if (!headerView) {
        //load the headerview xib
        
        [[NSBundle mainBundle] loadNibNamed:@"HeaderView" owner:self options:nil];
    }
    
    
    return headerView;
    
    
    
}




-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    
    //return the pointer to the archived views we created with the XIB
    
    return [self headerView];
    
}


-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

{
    //the height of the header view should be determined from the height of the
    //view in the XIB file
    
    return [[self headerView] bounds].size.height;
    
    
}



-(IBAction)toggleEditMode:(id)sender
{
    
    // if we aren't currently in editing mode
    
    if ([self isEditing]) {
        //change the text of the button to inform user
        [sender setTitle:@"Edit" forState:UIControlStateNormal];
        
        // turn off editing mode
        [self setEditing:NO animated:YES];
    } else
    {
        //change text of button to inform user of state
        [sender setTitle:@"done" forState:UIControlStateNormal];
        //Enter editing mode
        [self setEditing:YES animated:YES];
    }
    
    
    
}



-(IBAction)addNewItem:(id)sender
{
    //create a new BNRItem and add it to the store
    // because it UITableViewController asks the dataSource how many it should show
    // we need to add a new item
    
    BNRItem *newItem = [[BNRItemStore sharedStore] createItem];
    
    //figure out where the item is in the array
    
    int lastRow = [[[BNRItemStore sharedStore] allItems] indexOfObject:newItem];
    
    
    NSIndexPath *ip = [NSIndexPath indexPathForRow:lastRow inSection:0];
    
    
    //Insert this new row into the table
    
    [[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationTop];
    
    
    
}






-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    // create an instance of UITableViewCell, with default appearance
    
    UITableViewCell *cell =
    [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
   
    
    
    
    
    
    // set the text on the cell with the description of the item
    // that is at the nth index of items, where n = row this cell
    // will appear in on the tableview
    
    if (!cell) {
       cell =  [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
    }
    
    
    
    BNRItem *p = [[[BNRItemStore sharedStore] allItems] objectAtIndex:[indexPath row]];
    
    [[cell textLabel] setText:[p description]];
    
    return cell;
    
    
}



@end

BNRItem.h

#import <Foundation/Foundation.h>

@interface BNRItem : NSObject


    
  


@property (nonatomic, copy )NSString *itemName;
@property (nonatomic, copy )NSString *serialNumber;
@property (nonatomic)int       valueInDollars;
@property (nonatomic, readonly, strong)NSDate    *dateCreated;

@property (nonatomic, readwrite, strong)BNRItem *containedItem;
@property (nonatomic, readwrite, weak)BNRItem *container;



    
    
    

+(id)randomItem;

-(id)initWithItemName: (NSString *)name
        valueInDollars: (int)value
         serialNumber: (NSString *)sNumber;






@end

BNRItem.m

#import "BNRItem.h"

@implementation BNRItem



@synthesize containedItem, container, itemName, serialNumber, valueInDollars, dateCreated;




+(id)randomItem

{
    
    NSArray *randomAdjecitves = [[NSArray alloc] initWithObjects:@"fluffy", @"Rusty", @"Shiny", nil];
    
    NSArray *randomNouns = [[NSArray alloc] initWithObjects:@"bear", @"Spork", @"Mac", nil];
    
    
    //get and index of the random adjective or noun from the list
    
    
    NSInteger adjectivesIndex = rand() % [randomAdjecitves count];
    NSInteger nounsIndex = rand() % [randomNouns count];
    
    
    // now create a random name from both arrays
    
    
    NSString *randomName = [NSString stringWithFormat:@"%@ %@", [randomAdjecitves objectAtIndex:adjectivesIndex], [randomNouns objectAtIndex:nounsIndex]];
    
    
    // no create the serial number
    
    int randomValue = rand() % 100;
    
    
    
    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                    
                                    '0' +rand() % 10,
                                    'A' +rand() % 26,
                                    '0' +rand() % 10,
                                    'A' +rand() % 26,
                                    '0' +rand() % 10];
    
    
    BNRItem *newItem =
    
    [[self alloc] initWithItemName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber];
    
    return newItem;
    
    
    
    
}


-(void)setContainedItem:(BNRItem *)i
{
    
    containedItem = i;
    [i setContainer: self];
    
    
    
}


-(NSString *)description
{
 
    NSString *descriptionString = [[NSString alloc] initWithFormat:@" %@ (%@): Worth $%d, recorded on %@", itemName,
                                                                                                        serialNumber,
                                                                                                                                       valueInDollars,dateCreated];
    return descriptionString;
    
}



-(id)init
{
    return [self initWithItemName:@"item" valueInDollars:0 serialNumber:@""];
    
    
    
}




-(id)initWithItemName: (NSString *)name
       valueInDollars: (int)value
         serialNumber: (NSString *)sNumber
{
    
    //call superclasses designated init
    
    self = [super init];
    
    // give the instance variables initial values
    
    if (self) {
    
    [self setItemName:name];
    [self setValueInDollars:value];
    [self setSerialNumber:sNumber];
    dateCreated = [[NSDate alloc] init];
    
    }
    
    return self;
}

Not sure if it’s iOS 6 simulator acting funky or if I’ve made a mistake, but there is no reaction when I hit the new button.

Thanks


#2

Why is there so much white space in this code? Makes it really hard to follow what is going.


#3

Check your connections in your xib file.


#4

I double checked the IB connections . .

Ok so I’ve added NSLogs to the code to see if it actually adds the row when the button is pressed, it does, I just doesn’t animate it and show it in the iOS 6 simulator.

-(IBAction)addNewItem:(id)sender

-(IBAction)addNewItem:(id)sender
{
   
    //Logging allItems count before new row created
    NSInteger beforeCount = [[[BNRItemStore sharedStore] allItems] count];
    
    NSLog(@"row count: %d", beforeCount);
    
    
    
    
    
    
    //create a new BNRItem and add it to the store
    // because it UITableViewController asks the dataSource how many it should show
    // we need to add a new item
    
    BNRItem *newItem = [[BNRItemStore sharedStore] createItem];
    
   
   //figure out where the item is in the array
    
   int lastRow = [[[BNRItemStore sharedStore] allItems] indexOfObject:newItem];
    
    
    NSIndexPath *ip = [NSIndexPath indexPathForRow:lastRow inSection:0];
    
    
    //Insert this new row into the table
    
    [[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationBottom];
    
    //Logging allItems count after row added
    NSInteger afterCount = [[[BNRItemStore sharedStore] allItems] count];
    
    NSLog(@"row count: %d", afterCount);
}

I get:

row count: 20
row count: 21


#5

ok, so realised it’s actually doing everything except one thing. It’s adding the row, to the bottom of the list, not the top hmmm . . .