使用Core Data创建UITableView时出错和崩溃

时间:2014-07-29 02:28:50

标签: ios objective-c uitableview core-data nsmanagedobjectcontext

我尝试使用Core Data制作UITableView,但是当我运行它时遇到了崩溃:

014-07-29 10:13:12.443 TableAndCoreData[797:60b] -[AppDelegate managedObjectContext]: unrecognized selector sent to instance 0x8f319a0
2014-07-29 10:13:12.446 TableAndCoreData[797:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppDelegate managedObjectContext]: unrecognized selector sent to instance 0x8f319a0'

我通常检查它,我想这可能是创建managedObjectContext的问题。有没有人有想法帮我解决这个问题?

@interface DetailViewController ()

@property (weak, nonatomic) IBOutlet UITextField *nameTextField;
@property (weak, nonatomic) IBOutlet UITextField *ageTextField;

@end

@implementation DetailViewController

// Set NSManagedObjectContext
- (NSManagedObjectContext *) managedOjectContext
{
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication]delegate];
    if ([delegate performSelector:@selector(managedObjectContext)]) {
        context = [delegate managedOjectContext];
    }
    return context;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)cancelButton:(UIButton *)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)saveButton:(UIButton *)sender
{
    [self save];
}

- (void)save
{
    // Get ManagedObjectContext
    NSManagedObjectContext *context = [self managedOjectContext];

    // Create a ManagedObject
    NSManagedObject *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];

    // Set value for the attributes of the entity
    [aPerson setValue:self.nameTextField.text forKey:@"name"];
    [aPerson setValue:self.ageTextField.text forKey:@"age"];

    // Check the error
    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"Can't save due to %@%@", error, [error localizedDescription]);
    }

    [self dismissViewControllerAnimated:YES completion:nil];
}

此外,我正在尝试使用核心数据创建UITableView的另一种方式:

 - (void) save
{
    // Create UIManagedDocument
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *documentDirectory = [[fileManager URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask]firstObject];
    NSString *documentName = @"Model";
    NSURL *url = [documentDirectory URLByAppendingPathComponent:documentName];
    UIManagedDocument *document = [[UIManagedDocument alloc]initWithFileURL:url];
    if ([fileManager fileExistsAtPath:[url path]]) {
        [document openWithCompletionHandler:^(BOOL success) {
            if (success) {
                if (document.documentState == UIDocumentStateNormal) {
                    // Get a ManagedObjectContext
                    NSManagedObjectContext *context = document.managedObjectContext;

                    // Set managed object (entity)
                    NSManagedObject *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];

                    // Set value for the attribute (which are "name" and "age") of the entity
                    [aPerson setValue:self.nameTextField.text forKey:@"name"];
                    [aPerson setValue:self.ageTextField.text forKey:@"age"];

                    // Check whether there is an error
                    NSError *error = nil;
                    if (![context save:&error]) {
                        NSLog(@"Can't save due to %@%@", error, [error localizedDescription]);
                    }

                    // Close the window
                    [self dismissViewControllerAnimated:YES completion:nil];
                }
            }
            if (!success) {
                NSLog(@"couldn't open document at %@", url);
            }
        }];
    }
    else {
        [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            if (success) {
                if (document.documentState == UIDocumentStateNormal) {
                    // Get a ManagedObjectContext
                    NSManagedObjectContext *context = document.managedObjectContext;

                    // Set managed object (entity)
                    NSManagedObject *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];

                    // Set value for the attribute (which are "name" and "age") of the entity
                    [aPerson setValue:self.nameTextField.text forKey:@"name"];
                    [aPerson setValue:self.ageTextField.text forKey:@"age"];

                    // Check whether there is an error
                    NSError *error = nil;
                    if (![context save:&error]) {
                        NSLog(@"Can't save due to %@%@", error, [error localizedDescription]);
                    }

                    // Close the window
                    [self dismissViewControllerAnimated:YES completion:nil];
                }
            }
            if (!success) {
                NSLog(@"couldn't open document at %@", url);
            }
        }];
    }
}

然而,它无法找到UIManagedDocument。我真的很想知道为什么我应该创建一个UIManagedDocument以及我应该命名的文档名称。

1 个答案:

答案 0 :(得分:0)

您的崩溃与Core Data没有任何关系。

改变这个: [delegate performSelector:@selector(managedObjectContext)]

于: [delegate respondsToSelector:@selector(managedObjectContext)]

崩溃发生的原因是您将消息managedObjectContext发送到应用程序委托对象,该对象不响应该消息。它是在发送的,因为您要检查它是否用respondsToSelector:来回复该消息,而是performSelector。您的应用程序委托对象仍然需要实现managedObjectContext才能使您的代码正常运行,但您发布的部分不应再像您描述的那样崩溃。

通常,您希望避免以这种方式在应用程序委托上调用方法。最好在启动时将这样的值从应用程序委托传递到根视图控制器,然后传递给下一个视图控制器和下一个视图控制器。

Core Data documentation中有一个稍微过时但仍然相关的部分讨论了这个问题:

  

视图控制器通常不应从全局对象(例如应用程序委托)检索上下文 - 这会使应用程序体系结构变得僵硬。视图控制器也不应为自己的用途创建上下文(除非它是嵌套的上下文)。

...以及iOS 5 release notes

  

嵌套上下文使得采用“传递接力棒”方法访问上下文(通过将上下文从一个视图控制器传递到下一个)而不是直接从应用程序委托中检索它比以往任何时候都更重要。