views:

919

answers:

2

Hi,

I'm creating an app which uses a UINavigationController (which's view's nib is RootViewController.xib) located in MainWindow.xib, and a UITableView in RootViewController.xib. I have this code:

MainWindow.xib's UINavigationController

sorry, you need to be able to see this image

TDAppDelegate.h

//
//  To_DoAppDelegate.h
//  To Do
//
//  Created by Radek Slupik on 14-02-10.
//  Copyright RSONIC 2010. All rights reserved.
//

@interface TDAppDelegate : NSObject <UIApplicationDelegate> {
    // VARIABLES
    NSManagedObjectModel *managedObjectModel;
    NSManagedObjectContext *managedObjectContext;       
    NSPersistentStoreCoordinator *persistentStoreCoordinator;

    // IBOUTLETS
    UIWindow *window;
    UINavigationController *navigationController;
}

// PROPERTIES
@property(nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property(nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property(nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

@property(nonatomic, retain) IBOutlet UIWindow *window;
@property(nonatomic, retain) IBOutlet UINavigationController *navigationController;


// IBACTIONS


// METHODS
- (NSString *)applicationDocumentsDirectory;

@end

TDAppDelegate.m

//
//  To_DoAppDelegate.m
//  To Do
//
//  Created by Radek Slupik on 14-02-10.
//  Copyright RSONIC 2010. All rights reserved.
//

#import "TDAppDelegate.h"


@implementation TDAppDelegate

@synthesize window;
@synthesize navigationController;

// MEMORY
- (void)dealloc {
    [managedObjectContext release];
    [managedObjectModel release];
    [persistentStoreCoordinator release];

    [navigationController release];
    [window release];
    [super dealloc];
}

// APPLICATION

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [window makeKeyAndVisible];
    [window addSubview:[navigationController view]]; // IT GOES WRONG WHEN I DO THIS
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Save changes before quitting =D
    NSError *error = nil;
    if(managedObjectContext != nil) {
        if([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

// CORE DATA
- (NSManagedObjectContext *) managedObjectContext {
    // Returns the managed object context for the application. If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
    if(managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if(coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {
    // Returns the managed object model for the application. If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
    if(managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    // Returns the persistent store coordinator for the application. If the coordinator doesn't already exist, it is created and the application's store added to it.
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"To_Do.sqlite"]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        UIAlertView *quitAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"error", @"error")  message:[NSString stringWithFormat:NSLocalizedString(@"persistentstorecoordinator error", @""), [error userInfo]] delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
        [quitAlert show];
        [quitAlert release];
    }    

    return persistentStoreCoordinator;
}


- (NSString *)applicationDocumentsDirectory {
    // Returns the path to the application's Documents directory.
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

@end

TDRootViewController.h

//
//  TDRootViewController.h
//  To Do
//
//  Created by Radek Slupik on 14-02-10.
//  Copyright 2010 RSONIC. All rights reserved.
//

#import <UIKit/UIKit.h>


@interface TDRootViewController : UITableViewController <UITableViewDataSource> {
    NSMutableArray *todoArray;
    NSManagedObjectContext *managedObjectContext;

    UIBarButtonItem *addButton;
}

@property(nonatomic, retain) NSMutableArray *todoArray;
@property(nonatomic, retain) NSManagedObjectContext *managedObjectContext;

@property(nonatomic, retain) UIBarButtonItem *addButton;

@end

TDRootViewController.m

//
//  TDRootViewController.m
//  To Do
//
//  Created by Radek Slupik on 14-02-10.
//  Copyright 2010 RSONIC. All rights reserved.
//

#import "TDRootViewController.h"
#import "TodoItem.h"


@implementation TDRootViewController

// MEMORY
- (void)dealloc {
    [super dealloc];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
}

// VIEW
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        return YES;
    }
    return NO;
}

// TABLE VIEW

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Set up the cell...

    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
    // [self.navigationController pushViewController:anotherViewController];
    // [anotherViewController release];
}


/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
 */


/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/


/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

// METHODS
- (void)addItem {
    TodoItem *todoItem = (TodoItem *)[NSEntityDescription insertNewObjectForEntityForName:@"TodoItem" inManagedObjectContext:managedObjectContext];
}

@end

phew =D

Okay, my app compiles correctly, but when it starts, the holy Console says this:

[Session started at 2010-02-14 14:40:12 +0100.]
2010-02-14 14:40:15.245 To Do[1478:207] *** -[UIViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x3a155b0
2010-02-14 14:40:15.246 To Do[1478:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x3a155b0'
2010-02-14 14:40:15.246 To Do[1478:207] Stack: (
    30893147,
    2500113673,
    31275067,
    30844534,
    30697154,
    4364410,
    4371786,
    4370783,
    3087322,
    3027833,
    3069268,
    3057823,
    57406128,
    57405551,
    57403590,
    57402682,
    2731769,
    2755464,
    2737875,
    2764981,
    38989521,
    30677888,
    30673992,
    2731625,
    2768899,
    10592,
    10446
)

I think it has something to do with numberOfRowsInSection but I'm not sure. Can anyone help me out? Thanks

+1  A: 

I believe that you've connected the datasource's connection of the problematic UITableView (in Interface Builder) to wrong source.
It should be connected to file's owner.

Or the class of file's owner is not set to the correct view controller.

Post some screenshots from your IB.
Post the next screens:
- select the table view and press Cmd+2
- select the file's owner and press Cmd+4

Michael Kessler
A: 

You're right, it does have something to do with the -tableView:numberOfRowsInSection: method, that's why the error mentions that method specifically.

That method is one of the table view's data source methods. The "unrecognized selector" message means that the table view is attempting to call this method on an object that doesn't implement it. Since you implemented that method in TDRootViewController, you must have connected the data source to something else.

I don't think we have enough information to say where it is connected, but it's clearly connected wrongly. Look in IB, find this connection, and see where it leads. Then fix it so that it points to the right place, which would appear to be your instance of TDRootViewController.

Tom Harrington