Build Failure


#1

Hi,

I have copied all the code in the chapter and at this point have implementation warnings and an undeclared identifier which I assume is the culprit for the implementation errors.

Here is the Code:

BNRAppDelegate.h:

[code]//
// BNRAppDelegate.h
// iTahDoodle2
//
// Created by MICHAEL GILBERT on 05/04/2012.
// Copyright © 2012 MyCompanyName. All rights reserved.
//

#import <UIKit/UIKit.h>

//Declare a helper function that we will use to get a path
// to the location on disk where we can save the to do list
NSString *docPath(void);

@interface BNRAppDelegate : UIResponder
<UIApplicationDelegate, UITableViewDataSource>

{

UITableView *taskTable;
UITextField *taskField;
UIButton *insertButton;

NSMutableArray *tasks;

}

-(void)addTask:(id)sender;

@property (strong, nonatomic) UIWindow *window;

@end
[/code]

and my BNRAppDelegate.m:

[code]//
// BNRAppDelegate.m
// iTahDoodle2
//
// Created by MICHAEL GILBERT on 05/04/2012.
// Copyright © 2012 MyCompanyName. All rights reserved.
//

#import “BNRAppDelegate.h”

//helper function to fetch the path to our to-do data stored on disk
NSString *docPath()
{
NSArray *pathlist = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathlist objectAtIndex:0] stringByAppendingPathComponent:@“data.td”];
}

@implementation BNRAppDelegate <---- Xcode gives 2 incomplete implementation warnings here

@synthesize window = _window;

#pragma mark - Application delegate callbacks

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    //Attempt to Load an existing to-do dataset from an array stored to disk.
    NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
    if (plist) {
    //If there is a database available, copy it into our instance variable
    tasks = [plist mutableCopy];
    }else {
    //otherwise, just create an empty one to get us started.
    tasks = [[NSMutableArray alloc] init];
    }

    // is task empty?

    if([tasks count] == 0) {
    [tasks addObject:@“meditate”];
    [tasks addObject:@“song”];
    [tasks addObject:@“code”];

    }

    //Create and configure the UIWindow instance
    //A CGRect is a struct with an origin (x,y) and size (width, height)

    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    UIWindow *theWindow = [[UIWindow alloc] initWithFrame:windowFrame];
    [self setWindow:theWindow];

    //Define the frame rectangles of the three UI elements
    // CGRectMake() creates a CGRect from (x, y, width, height)
    CGRect tableFrame = CGRectMake(0, 80, 320, 380);
    CGRect fieldFrame = CGRectMake(20, 40, 200, 31);
    CGRect buttonFrame = CGRectMake(228, 40, 72, 31);

    //Create and configure the table view
    taskTable = [[UITableView alloc] initWithFrame:tableFrame
    style:UITableViewStylePlain];
    [taskTable setSeparatorStyle:UITableViewCellSeparatorStyleNone];

    //Make this object the table view’s dataSource
    [taskTable setDataSource:self];

    //create and configure the text field where new tasks will be typed
    taskField = [[UITextField alloc] initWithFrame:fieldFrame];
    [taskField setBorderStyle:UITextBorderStyleRoundedRect];
    [taskField setPlaceholder:@“type as task, tap insert”];

    //create and configure a rounded insurt button
    insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [insertButton setFrame:buttonFrame];

    //Buttons behave using a target/action callback
    insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [insertButton addTarget:self
    action:@selector(addTask:)
    forControlEvents:UIControlEventTouchUpInside];

    //Give the button a title
    [insertButton setTitle:@"Insert"
    forState:UIControlStateNormal];

    //Add our three UI elements to the window
    [[self window] addSubview:taskTable];
    [[self window] addSubview:taskField];
    [[self window] addSubview:insertButton];

    //Finalise the window and put it on the screen
    [[self window] setBackgroundColor:[UIColor whiteColor]];
    [[self window] makeKeyAndVisible];

    return YES;

#pragma mark - Table View management

- (NSInteger)tableView:(UITableView *)tableView                    <------- Xcode says 'tableView' undeclared identifier and suggests 'UITableView'
numberOfRowsInSection:(NSInteger)section
{
    // table view only has one section
    // number rows is equal to number of items in task array
    
    return [tasks count]; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//To improve performance, we reconfigure cells in memory
// that have scrolled off the screen and hand them back
//with new contents instead of always creating new cells.
//First, we check to see if there’s a cell available for reuse.

    UITableViewCell *c = [taskTable dequeueReusableCellWithIdentifier:@"Cell"];
    
    if(!c) {
        // . . . only allocate a new cell if none are available
        c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:@"Cell"];
        
    }

//Then we (re)configure the cell based on the model object,
    //in this case our todoItems array
    NSString *item = [tasks objectAtIndex:[indexPath row]];
    [[c textLabel] setText:item];
    
    //and hand back toe the table view the properly configured cell
    return c;
    
}
 

- (void)addTask:(id)sender
{
    //Get the to do item
    NSString *t = [taskField text];
    
    //
    if([t isEqualToString:@""]) {
        return ;
    }

// Add it to our working array
    [tasks addobject:t];
    //Refresh the table so that new item shows up
    [taskTable reloadData];
    //And clear out the text field
    [taskField setText:@""];
    //Dissmiss the keyboard
    [taskField resignFirstResponder];




}

/*
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
 */
 
 }
  • (void)applicationWillResignActive:(UIApplication *)application
    {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application
    {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

//This method is only called in ios 4.0+
// Save our task array to disk
[tasks writeToFile:docPath() atomically:YES];

}

  • (void)applicationWillEnterForeground:(UIApplication *)application
    {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

  • (void)applicationDidBecomeActive:(UIApplication *)application
    {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

  • (void)applicationWillTerminate:(UIApplication *)application
    {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

//This method is only called in iOS versions prior to 4.0
// save our tasks array to disks
[tasks writeToFile:docPath() atomically:YES];

}

@end
[/code]

Thanks a lot for your time and help! This is a great Forum!


#2

i’m starting to think I messed up with curly braces somewhere, just trying to find where now! . . .


#3

I’ve gone through my .m again, still getting the same errors hmmm:

[code]//
// BNRAppDelegate.m
// iTahDoodle2
//
// Created by MICHAEL GILBERT on 05/04/2012.
// Copyright © 2012 MyCompanyName. All rights reserved.
//

#import “BNRAppDelegate.h”

//helper function to fetch the path to our to-do data stored on disk
NSString *docPath()
{
NSArray *pathlist = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathlist objectAtIndex:0] stringByAppendingPathComponent:@“data.td”];
}

@implementation BNRAppDelegate

@synthesize window = _window;

#pragma mark - Application delegate callbacks

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    //Attempt to Load an existing to-do dataset from an array stored to disk.
    NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
    if (plist) {
    //If there is a database available, copy it into our instance variable
    tasks = [plist mutableCopy];
    }else {
    //otherwise, just create an empty one to get us started.
    tasks = [[NSMutableArray alloc] init];
    }

    // is task empty?

    if([tasks count] == 0) {
    [tasks addObject:@“meditate”];
    [tasks addObject:@“song”];
    [tasks addObject:@“code”];
    }

    //Create and configure the UIWindow instance
    //A CGRect is a struct with an origin (x,y) and size (width, height)

    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    UIWindow *theWindow = [[UIWindow alloc] initWithFrame:windowFrame];
    [self setWindow:theWindow];

    //Define the frame rectangles of the three UI elements
    // CGRectMake() creates a CGRect from (x, y, width, height)
    CGRect tableFrame = CGRectMake(0, 80, 320, 380);
    CGRect fieldFrame = CGRectMake(20, 40, 200, 31);
    CGRect buttonFrame = CGRectMake(228, 40, 72, 31);

    //Create and configure the table view
    taskTable = [[UITableView alloc] initWithFrame:tableFrame
    style:UITableViewStylePlain];
    [taskTable setSeparatorStyle:UITableViewCellSeparatorStyleNone];

    //Make this object the table view’s dataSource
    [taskTable setDataSource:self];

    //create and configure the text field where new tasks will be typed
    taskField = [[UITextField alloc] initWithFrame:fieldFrame];
    [taskField setBorderStyle:UITextBorderStyleRoundedRect];
    [taskField setPlaceholder:@“type as task, tap insert”];

    //create and configure a rounded insurt button
    insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [insertButton setFrame:buttonFrame];

    //Buttons behave using a target/action callback
    insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [insertButton addTarget:self
    action:@selector(addTask:)
    forControlEvents:UIControlEventTouchUpInside];

    //Give the button a title
    [insertButton setTitle:@"Insert"
    forState:UIControlStateNormal];

    //Add our three UI elements to the window
    [[self window] addSubview:taskTable];
    [[self window] addSubview:taskField];
    [[self window] addSubview:insertButton];

    //Finalise the window and put it on the screen
    [[self window] setBackgroundColor:[UIColor whiteColor]];
    [[self window] makeKeyAndVisible];

    return YES;

#pragma mark - Table View management

- (NSInteger)tableView:(UITableView *)tableView 
numberOfRowsInSection:(NSInteger)section
{
    // table view only has one section
    // number rows is equal to number of items in task array
    
    return [tasks count]; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//To improve performance, we reconfigure cells in memory
// that have scrolled off the screen and hand them back
//with new contents instead of always creating new cells.
//First, we check to see if there’s a cell available for reuse.

    UITableViewCell *c = [taskTable dequeueReusableCellWithIdentifier:@"Cell"];
    
    if(!c) {
        // . . . only allocate a new cell if none are available
        c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:@"Cell"];
        
    }

//Then we (re)configure the cell based on the model object,
    //in this case our todoItems array
    NSString *item = [tasks objectAtIndex:[indexPath row]];
    [[c textLabel] setText:item];
    
    //and hand back toe the table view the properly configured cell
    return c;
}  

 
- (void)addTask:(id)sender
{
    //Get the to do item
    NSString *t = [taskField text];
    
    //
   if ([t length] == 0)]) {
        return ;
    }

// Add it to our working array
    [tasks addobject:t];
    //Refresh the table so that new item shows up
    [taskTable reloadData];
    //And clear out the text field
    [taskField setText:@""];
    //Dissmiss the keyboard
    [taskField resignFirstResponder];
}






/*
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
 */

}

  • (void)applicationWillResignActive:(UIApplication *)application
    {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application
    {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

//This method is only called in ios 4.0+
// Save our task array to disk
[tasks writeToFile:docPath() atomically:YES];

}

  • (void)applicationWillEnterForeground:(UIApplication *)application
    {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

  • (void)applicationDidBecomeActive:(UIApplication *)application
    {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

  • (void)applicationWillTerminate:(UIApplication *)application
    {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

//This method is only called in iOS versions prior to 4.0
// save our tasks array to disks
[tasks writeToFile:docPath() atomically:YES];

}

@end
[/code]


#4

Include the error so that we know what we are looking for.


#5

Sorry about that . . .

Here is the error list, I’ve put a marking ( <-------) pointing to where they occur in the code below:

Error 1 (Red !): " Semantic Issue: 'use of undeclared identifier ‘tableView’. Did you mean ‘UITableView’? "

Error 2 (Yellow !): Semantic Issue: “incomplete implementation”

Error 3 (Yellow !): Semantic Issue: Method in protocol not implemented

  • (!) Method declared here: highlights the line in code: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

  • (!) Required for direct or indirect: highlights this line in code of .h: @interface BNRAppDelegate : UIResponder

My BNRAppDelegate.h

[code]//
// BNRAppDelegate.h
// iTahDoodle2
//
// Created by MICHAEL GILBERT on 05/04/2012.
// Copyright © 2012 MyCompanyName. All rights reserved.
//

#import <UIKit/UIKit.h>

//Declare a helper function that we will use to get a path
// to the location on disk where we can save the to do list
NSString *docPath(void);

@interface BNRAppDelegate : UIResponder
<UIApplicationDelegate, UITableViewDataSource>

{

UITableView *taskTable;
UITextField *taskField;
UIButton *insertButton;

NSMutableArray *tasks;

}

-(void)addTask:(id)sender;

@property (strong, nonatomic) UIWindow *window;

@end
[/code]

My BNRAppDelegate.m:

[code]//
// BNRAppDelegate.m
// iTahDoodle2
//
// Created by MICHAEL GILBERT on 05/04/2012.
// Copyright © 2012 MyCompanyName. All rights reserved.
//

#import “BNRAppDelegate.h”

//helper function to fetch the path to our to-do data stored on disk
NSString *docPath()
{
NSArray *pathlist = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathlist objectAtIndex:0] stringByAppendingPathComponent:@“data.td”];
}

@implementation BNRAppDelegate <— Error 2 & Error 3

@synthesize window = _window;

#pragma mark - Application delegate callbacks

  • (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{
//Attempt to Load an existing to-do dataset from an array stored to disk.
NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
if (plist) {
//If there is a database available, copy it into our instance variable
tasks = [plist mutableCopy];
}else {
//otherwise, just create an empty one to get us started.
tasks = [[NSMutableArray alloc] init];
}

// is task empty?

if([tasks count] == 0) {
    [tasks addObject:@"meditate"];
    [tasks addObject:@"song"];
    [tasks addObject:@"code"];
}    

//Create and configure the UIWindow instance
//A CGRect is a struct with an origin (x,y) and size (width, height)

CGRect windowFrame = [[UIScreen mainScreen] bounds];
UIWindow *theWindow = [[UIWindow alloc] initWithFrame:windowFrame];
[self setWindow:theWindow];

//Define the frame rectangles of the three UI elements
// CGRectMake() creates a CGRect from (x, y, width, height)
CGRect tableFrame = CGRectMake(0, 80, 320, 380);
CGRect fieldFrame = CGRectMake(20, 40, 200, 31);
CGRect buttonFrame = CGRectMake(228, 40, 72, 31);

//Create and configure the table view
taskTable = [[UITableView alloc] initWithFrame:tableFrame 
                                         style:UITableViewStylePlain];
[taskTable setSeparatorStyle:UITableViewCellSeparatorStyleNone];

//Make this object the table view's dataSource
[taskTable setDataSource:self];

//create and configure the text field where new tasks will be typed
taskField = [[UITextField alloc] initWithFrame:fieldFrame];
[taskField setBorderStyle:UITextBorderStyleRoundedRect];
[taskField setPlaceholder:@"type as task, tap insert"];



//create and configure a rounded insurt button
insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[insertButton setFrame:buttonFrame];



//Buttons behave using a target/action callback
insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[insertButton addTarget:self 
                 action:@selector(addTask:) 
                    forControlEvents:UIControlEventTouchUpInside];


//Give the button a title
[insertButton setTitle:@"Insert" 
              forState:UIControlStateNormal];


//Add our three UI elements to the window
[[self window] addSubview:taskTable];
[[self window] addSubview:taskField];
[[self window] addSubview:insertButton];

//Finalise the window and put it on the screen
[[self window] setBackgroundColor:[UIColor whiteColor]];
[[self window] makeKeyAndVisible];

return YES;

#pragma mark - Table View management

- (NSInteger)tableView:(UITableView *)tableView    <----- Error 1
numberOfRowsInSection:(NSInteger)section
{
    // table view only has one section
    // number rows is equal to number of items in task array
    
    return [tasks count]; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//To improve performance, we reconfigure cells in memory
// that have scrolled off the screen and hand them back
//with new contents instead of always creating new cells.
//First, we check to see if there’s a cell available for reuse.

    UITableViewCell *c = [taskTable dequeueReusableCellWithIdentifier:@"Cell"];
    
    if(!c) {
        // . . . only allocate a new cell if none are available
        c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:@"Cell"];
        
    }

//Then we (re)configure the cell based on the model object,
    //in this case our todoItems array
    NSString *item = [tasks objectAtIndex:[indexPath row]];
    [[c textLabel] setText:item];
    
    //and hand back toe the table view the properly configured cell
    return c;
}  

 
- (void)addTask:(id)sender
{
    //Get the to do item
    NSString *t = [taskField text];
    
    //
   if ([t length] == 0) {
        return ;
    }

// Add it to our working array
    [tasks addobject:t];
    //Refresh the table so that new item shows up
    [taskTable reloadData];
    //And clear out the text field
    [taskField setText:@""];
    //Dissmiss the keyboard
    [taskField resignFirstResponder];
}






/*
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
 */

}

  • (void)applicationWillResignActive:(UIApplication *)application
    {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application
    {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

//This method is only called in ios 4.0+
// Save our task array to disk
[tasks writeToFile:docPath() atomically:YES];

}

  • (void)applicationWillEnterForeground:(UIApplication *)application
    {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

  • (void)applicationDidBecomeActive:(UIApplication *)application
    {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

  • (void)applicationWillTerminate:(UIApplication *)application
    {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.

//This method is only called in iOS versions prior to 4.0
// save our tasks array to disks
[tasks writeToFile:docPath() atomically:YES];

}

@end[/code]


#6

This is one of those times where the actual error message is only partially related to the problem.

You’re missing a close-curly at the end of your application:didFinishLaunchingWithOptions: method, which is causing the compiler to not properly acknowledge your tableView:numberOfRowsInSection: (and following) method(s). I expect all three issues are tied to the same root cause.

Xcode is generally pretty intelligent about its auto-indentation of your code. If you notice that the indentation level has changed to an unexpected level when you hit return, it’s likely that you have mismatched curlies somewhere.


#7

Thanks Mikey! . . . for some reason it didn’t compute that these other methods hung out outside. Of course it’s all just code, why wouldn’t they?


#8

Only problem now, is InsertButton does not show up when I run it in the simulator

P.S. after adding curly brace found out my 'Adding new tasks section of the code had a mistake:

I changed
addobject ----> addObject