0

I keep getting the exception shown below. I Can't seem to figure it out why. Please help. Will email code if someone is willing to help

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ContactDBAppDelegate 0x4d45dc0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key navigationController.'

ContactDBAppDelegate.h

@interface ContactDBAppDelegate : NSObject <UIApplicationDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;       
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UINavigationController *navCtrl;
UIWindow *window;
}

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, retain) UINavigationController *navCtrl;
@property (nonatomic, retain) IBOutlet UIWindow *window;

- (NSString *)applicationDocumentsDirectory;

ContactDBAppDelegate.m

#import "ContactDBAppDelegate.h"
#import "RootViewController.h"

@implementation ContactDBAppDelegate
@synthesize navCtrl;
@synthesize window;


#pragma mark -
#pragma mark Application lifecycle

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
RootViewController *rootViewController = [[RootViewController alloc] init]; 
rootViewController.managedObjectContext = [self managedObjectContext] ; 
navCtrl = [[UINavigationController alloc] initWithRootViewController: rootViewController];

[window addSubview: navCtrl.view];
[window makeKeyAndVisible];

[rootViewController release]; // Must release here - locally declared...
}

/**
 applicationWillTerminate: saves changes in the application's managed object context before the application terminates.
 */

- (void)applicationWillTerminate:(UIApplication *)application {

NSError *error = nil;
if (managedObjectContext != nil) {
    if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    } 
}
}


#pragma mark -
#pragma mark Core Data stack

/**
 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.
 */

- (NSManagedObjectContext *) managedObjectContext {

if (managedObjectContext != nil) {
    return managedObjectContext;
}

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


/**
 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.
 */

- (NSManagedObjectModel *)managedObjectModel {

if (managedObjectModel != nil) {
    return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
return managedObjectModel;
}


/**
 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.
 */

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
}

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

NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
    /*
     Replace this implementation with code to handle the error appropriately.

     abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.

     Typical reasons for an error here include:
     * The persistent store is not accessible
     * The schema for the persistent store is incompatible with current managed object model
     Check the error message to determine what the actual problem was.
     */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}    

return persistentStoreCoordinator;
}


#pragma mark -
#pragma mark Application's Documents directory

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


#pragma mark -
#pragma mark Memory management

- (void)dealloc {
[managedObjectContext release];
[managedObjectModel release];
[persistentStoreCoordinator release];
[navCtrl release];
[window release];
[super dealloc];
}


@end

RootViewController.h

#import <UIKit/UIKit.h>
#import "EditViewController.h"

@interface RootViewController : UITableViewController {
NSMutableArray *contactItems;
NSManagedObjectContext *managedObjectContext; 
EditViewController *editViewCtrl;
}

@property(nonatomic, retain) NSMutableArray *contactItems;
@property(nonatomic, retain) NSManagedObjectContext *managedObjectContext; 
@property(nonatomic, retain) EditViewController *editViewCtrl;

- (void) addItem;

@end

RootViewController.m

#import "RootViewController.h"
#import "Contact.h"

@implementation RootViewController
@synthesize contactItems;
@synthesize managedObjectContext;
@synthesize editViewCtrl;

- (void)viewDidLoad {
[super viewDidLoad];

// Set the table style and title
[self initWithStyle: UITableViewStyleGrouped];
self.title = @"Contacts";

// Set up the add and delete bar buttons
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]    initWithBarButtonSystemItem: UIBarButtonSystemItemAdd target:self action:@selector(addItem)]; 

// Generate a fetch request for reading from the database and set its entity property 
NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName: @"Contact"  inManagedObjectContext: managedObjectContext];
request.entity = entity;
[entity release];

// Indicate how the fetched results are to be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"name" ascending: YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects: sortDescriptor, nil];
request.sortDescriptors = sortDescriptors;
[sortDescriptor release]; 

// Perform the actual fetch from the permanent store and initialize the menuItems array with the results
NSError *error = nil; 
contactItems = [[managedObjectContext executeFetchRequest: request error: &error] mutableCopy]; 
[request release];

// Creat the edit view controller
editViewCtrl = [[EditViewController alloc] init];

}

- (void) addItem {
// Insert a new record in the database
Contact *contact = [NSEntityDescription insertNewObjectForEntityForName: @"Contact" inManagedObjectContext: managedObjectContext];
NSError *error = nil; 
[managedObjectContext save: &error];

// Insert a new item in the table's data source
[contactItems insertObject: contact atIndex: 0];

// Insert a new row in the table
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: 0 inSection: 0]; 
[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade];
}


- (void) viewWillAppear: (BOOL) animated { 
[super viewWillAppear: animated];
if(editViewCtrl.contact) 
{
    NSIndexPath *path = [NSIndexPath indexPathForRow: [contactItems indexOfObject: editViewCtrl.contact] inSection: 0];
    NSArray *paths = [NSArray arrayWithObjects: path, nil]; 
    [self.tableView reloadRowsAtIndexPaths: paths withRowAnimation: NO]; 
    editViewCtrl.contact = nil;
}
}


#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}


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


// 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];

Contact *contact = [contactItems objectAtIndex: indexPath.row]; 
cell.textLabel.text = [NSString stringWithFormat:@"%@", contact.name]; 
cell.textLabel.font = [UIFont fontWithName: @"Helvetica-Bold" size: 14];
cell.textLabel.textColor = [UIColor blackColor];

return cell;
}




- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
editViewCtrl.contact = [contactItems objectAtIndex: indexPath.row]; 
[self.navigationController pushViewController: editViewCtrl animated:YES];
}




- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}




- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) 
{
    // Delete item from the context and save the context. This removes the item from the permanent store.
    [managedObjectContext deleteObject: [contactItems objectAtIndex: indexPath.row]];
    NSError *error = nil;
    [managedObjectContext save: &error];

    // Remove the item from the table's data source array
    [contactItems removeObjectAtIndex: indexPath.row];

    // Delete the item from the table itself.
    [tableView deleteRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: YES];
}   

}




- (void)dealloc {
[contactItems release];
[managedObjectContext release];
[editViewCtrl release];
[super dealloc];
}


@end

EditViewController.h

#import <UIKit/UIKit.h>

#import "Contact.h"

@interface EditViewController : UIViewController <UITextFieldDelegate> {
UILabel *lbl1, *lbl2, *lbl3;
UITextField *contactName;
UITextField *contactMobile;
UITextField *contactHome;
UIButton *done;
Contact *contact;
}

@property(nonatomic, retain) Contact *contact;

@end

EditViewController.m

#import "EditViewController.h"

#import "Contact.h"

@implementation EditViewController
@synthesize contact;


- (void)viewDidLoad {
[super viewDidLoad];

lbl1 = [[UILabel alloc] initWithFrame: CGRectMake(50, 0, 100, 30)];
lbl1.text = @"Contact Name";
lbl1.font = [UIFont fontWithName: @"Helvetica" size: 15];
lbl1.textColor = [UIColor blueColor];
[self.view addSubview: lbl1];

contactName = [[UITextField alloc] initWithFrame: CGRectMake(50, 30, 220, 30)];
contactName.borderStyle = UITextBorderStyleRoundedRect;
contactName.textColor = [UIColor blackColor];   
contactName.delegate = self;
[self.view addSubview: contactName];


lbl2 = [[UILabel alloc] initWithFrame: CGRectMake(50, 70, 100, 30)];
lbl2.text = @"Mobile Number";
lbl2.font = [UIFont fontWithName: @"Helvetica" size: 15];
lbl2.textColor = [UIColor blueColor];
[self.view addSubview: lbl2];

contactMobile = [[UITextField alloc] initWithFrame: CGRectMake(50, 100, 220, 30)];
contactMobile.borderStyle = UITextBorderStyleRoundedRect;
contactMobile.textColor = [UIColor blackColor]; 
contactMobile.delegate = self;
[self.view addSubview: contactMobile];

lbl3 = [[UILabel alloc] initWithFrame: CGRectMake(50, 140, 100, 30)];
lbl3.text = @"Home Number";
lbl3.font = [UIFont fontWithName: @"Helvetica" size: 15];
lbl3.textColor = [UIColor blueColor];
[self.view addSubview: lbl3];

contactHome = [[UITextField alloc] initWithFrame: CGRectMake(50, 170, 220, 30)];
contactHome.borderStyle = UITextBorderStyleRoundedRect;
contactHome.textColor = [UIColor blackColor];   
contactHome.delegate = self;
[self.view addSubview: contactHome];

done = [UIButton buttonWithType: UIButtonTypeRoundedRect];
done.frame = CGRectMake(0, 0, 60, 40);
done.center = CGPointMake(160, 380);
[done setTitle:@"Done" forState:UIControlStateNormal];
[done addTarget:self action:@selector(finishedEditing) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: done];

}


- (void) finishedEditing {
[self viewWillDisappear: YES];
}



- (void) viewWillAppear: (BOOL) animated { 
[super viewWillAppear: animated]; 
contactName.text = contact.name; 
contactMobile.text = [NSString stringWithFormat: @"%2.2f", [contact.mobile floatValue]]; 
}



- (void)viewWillDisappear:(BOOL)animated {
contact.name = contactName.text; 
contact.mobile = [NSNumber numberWithFloat: [contactMobile.text floatValue]];
NSManagedObjectContext *context = contact.managedObjectContext; 
NSError *error = nil; 
[context save: &error];
[self.navigationController popViewControllerAnimated: YES];

}



- (void) textFieldDidEndEditing: (UITextField *) txtField { 
if (txtField == contactName)
    contact.name = txtField.text; 
else if (txtField == contactMobile)
    contact.mobile = [NSNumber numberWithFloat: [txtField.text floatValue]]; 
}



- (BOOL) textFieldShouldReturn: (UITextField *) txtField {
[txtField resignFirstResponder];
return YES;
}



- (void)dealloc {
[contact release];
[lbl1 release];
[lbl2 release];
[contactMobile release];
[contactName release];
[done release];
[super dealloc];
}


@end

Contact.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>


@interface Contact : NSManagedObject {
@private
}
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * work;
@property (nonatomic, retain) NSNumber * mobile;
@property (nonatomic, retain) NSNumber * home;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * email;

@end

Contact.m

#import "Contact.h"


@implementation Contact
@dynamic name;
@dynamic work;
@dynamic mobile;
@dynamic home;
@dynamic address;
@dynamic email;

@end
competent_tech
  • 44,465
  • 11
  • 90
  • 113
  • 1
    Post the code that is causing the error, please. – PengOne Nov 07 '11 at 23:26
  • Posting all of your code is almost as bad as posting none of it. Please indicate the line where the error is occurring and post only the relevant code. Most people are not willing to read through your entire project to find the problem when a debugger can help you narrow it down to a few relevant lines. – PengOne Nov 09 '11 at 05:03

1 Answers1

1

wow, you posted your whole app! No offense intended but you need to learn how view controllers work. I strongly recommended digging into the Apple docs.

You may have other issues but start with this. You should never sending viewWillDisappear explicitly. Your view controller will receive that message from the OS. You should make at least the following changes:

- (void) finishedEditing {
    // DON'T DO THIS
    // [self viewWillDisappear: YES];

    // DO THIS
    contact.name = contactName.text; 
    contact.mobile = [NSNumber numberWithFloat: [contactMobile.text floatValue]];
    NSManagedObjectContext *context = contact.managedObjectContext; 
    NSError *error = nil; 
    [context save: &error];
    [self.navigationController popViewControllerAnimated:YES];
}

You should commit changes to the data model based on the appropriate user action or app trigger. Being notified that the view will disappear is not a good place to do that. Also, you should not pop the navigation controller stack from viewWillDisappear..

So, all the stuff you did in viewWillDisappear shouldn't happen there.

- (void)viewWillDisappear:(BOOL)animated {
    // contact.name = contactName.text; 
    // contact.mobile = [NSNumber numberWithFloat: [contactMobile.text floatValue]];
    // NSManagedObjectContext *context = contact.managedObjectContext; 
    // NSError *error = nil; 
    // [context save: &error];
    // [self.navigationController popViewControllerAnimated: YES];
}
XJones
  • 21,959
  • 10
  • 67
  • 82
  • Thank you for the response. Im very new to IPhone programming. Thanks for the help but its still throwing the exception. – user1034642 Nov 08 '11 at 00:43
  • you clearly have other issues. the error specifically is referring to a reference to the key `navigationController` on your app delegate object. Your app delegate doesn't have `navigationController` as a property. The code you posted doesn't show this. You should look in your NIB files and see if there is anything references the non-existent `navigationController` outlet on your app delegate. – XJones Nov 08 '11 at 00:47