我一直得到如下所示的异常。我似乎无法弄明白为什么。请帮忙。如果有人愿意提供帮助,将通过电子邮件发送代码
*** 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
答案 0 :(得分:1)
您可能还有其他问题,但请从此开始。您不应该明确发送viewWillDisappear
。您的视图控制器将从操作系统接收该消息。您应该至少进行以下更改:
- (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];
}
您应该根据相应的用户操作或应用触发器提交对数据模型的更改。被通知视图将消失不是一个好的地方。也, 你不应该从viewWillDisappear弹出导航控制器堆栈。
所以,你在viewWillDisappear
中所做的所有事情都不应该发生在那里。
- (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];
}