2013-08-28 36 views
3

当我尝试从Core Data将数据加载到Table View控制器时出现错误。我相信这是由于managedObject没有正确传递。'+ entityForName:nil不是合法的NSManagedObjectContext

但我相信我在使用didFinishLaunchingWithOptions下的AppDelegate.m中的代码进行了一些研究之后这样做了。

错误

***终止应用程序由于未捕获的异常 'NSInvalidArgumentException',原因是: '+ entityForName:无不是合法的NSManagedObjectContext参数搜索实体名称'俱乐部'

MLVAPPDelegate.h

#import <UIKit/UIKit.h> 

@interface MLVAppDelegate : UIResponder <UIApplicationDelegate> 

@property (strong, nonatomic) UIWindow *window; 

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 

@end 

MLVAppDelegate.m

#import "MLVAppDelegate.h" 
#import "MLVSyncEngine.h" 
#import "Club.h" 
#import "IronSet.h" 
#import "MLVClubSelectionViewController.h" 


@implementation MLVAppDelegate 

@synthesize managedObjectContext = _managedObjectContext; 
@synthesize managedObjectModel = _managedObjectModel; 
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    UITabBarController *tabController = (UITabBarController *)self.window.rootViewController; 

    UINavigationController *navigationController = (UINavigationController *)[[tabController viewControllers] objectAtIndex:0]; 
    MLVClubSelectionViewController *controller = (MLVClubSelectionViewController *)[[navigationController viewControllers] objectAtIndex:0]; 
    controller.managedObjectContext = self.managedObjectContext; 

    [[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[Club class]]; 

    [[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[IronSet class]]; 

    return YES; 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    [[MLVSyncEngine sharedEngine] startSync]; 
} 

- (NSManagedObjectContext *)masterManagedObjectContext { 
    if (_managedObjectContext != nil) { 
     return _managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     [_managedObjectContext performBlockAndWait:^{ 
      [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 
     }]; 
    } 
    return _managedObjectContext; 
} 
- (NSManagedObjectModel *)managedObjectModel 
{ 
    if (_managedObjectModel != nil) { 
     return _managedObjectModel; 
    } 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"GolfCalculator" withExtension:@"momd"]; 
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    return _managedObjectModel; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    if (_persistentStoreCoordinator != nil) { 
     return _persistentStoreCoordinator; 
    } 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"GolfCalculator.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]); 
     abort(); 
    } 

    return _persistentStoreCoordinator; 
} 

#pragma mark - Application's Documents directory 

// Returns the URL to the application's Documents directory. 
- (NSURL *)applicationDocumentsDirectory 
{ 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
} 

@end 

MLVClubSelectionViewController.h

#import <UIKit/UIKit.h> 

@interface MLVClubSelectionViewController : UITableViewController 

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController; 

@end 

MLVClubSelectionViewController.m

#import "MLVClubSelectionViewController.h" 
#import "Club.h" 
#import "IronSet.h" 
#import "MLVCoreDataController.h" 

@interface MLVClubSelectionViewController() 

@end 

@implementation MLVClubSelectionViewController 
@synthesize managedObjectContext; 
@synthesize fetchedResultsController = _fetchedResultsController; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSError *error; 
    if (![[self fetchedResultsController] performFetch:&error]) { 
     // Update to handle the error appropriately. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); // Fail 
    } 

    self.title = @"Club Selection"; 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
#warning Potentially incomplete method implementation. 
    // Return the number of sections. 
    return 0; 
} 

- (NSInteger)tableView:(UITableView *)tableView 
numberOfRowsInSection:(NSInteger)section { 
    id sectionInfo = 
    [[_fetchedResultsController sections] objectAtIndex:section]; 
    return [sectionInfo numberOfObjects]; 
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 
    Club *info = [_fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = info.fullTitle; 
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@", 
           info.model, info.level]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView 
     cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = 
    [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    // Set up the cell... 
    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 


#pragma mark - Table view delegate 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

} 

#pragma mark - Fetched Results 
- (NSFetchedResultsController *)fetchedResultsController { 

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

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription 
            entityForName:@"Club" inManagedObjectContext:managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] 
           initWithKey:@"make" ascending:NO]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; 

    [fetchRequest setFetchBatchSize:20]; 

    NSFetchedResultsController *theFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
             managedObjectContext:managedObjectContext sectionNameKeyPath:nil 
                cacheName:@"Root"]; 
    self.fetchedResultsController = theFetchedResultsController; 
    _fetchedResultsController.delegate = self; 

    return _fetchedResultsController; 
} 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates. 
    [self.tableView beginUpdates]; 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 

    UITableView *tableView = self.tableView; 

    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeUpdate: 
      [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
      break; 

     case NSFetchedResultsChangeMove: 
      [tableView deleteRowsAtIndexPaths:[NSArray 
               arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [tableView insertRowsAtIndexPaths:[NSArray 
               arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
    [self.tableView endUpdates]; 
} 
- (void)viewDidUnload { 
    self.fetchedResultsController = nil; 
} 

@end 
+0

'managedObjectController'如何在您的应用程序委托上设置?在你的'MLVClubSelectionViewController'上设置'managedObjectController'之前,必须要做到这一点。此外,“UINavigationController”的子类很不寻常 - 你可以在没有这样做的情况下构建你的应用程序。 – nielsbot

+0

我从另一个SO问题的研究中做了一个子类,在那里他们为tab控制器提出了这个问题。 – thebusiness11

+0

我用完整的AppDelegate更新了managedObjectController的设置。 – thebusiness11

回答

1

您制定的方法masterManagedObjectContext,但你永远不会说它。您将上下文传递给您的控制器,而不是将managedObjectContext属性的值(因为所有对象属性都将初始化为nil)分配值。

你可以做以下之一:

  1. 重命名masterManagedObjectContextmanagedObjectContext,这将提供managedObjectContext访问的懒洋洋地加载执行(这意味着self.managedObjectContext不应该再评估为nil
  2. 您可以选择执行managedObjectContext如下:

    - (NSManagedObjectContext *)managedObjectContext { 
        return [self masterManagedObjectContext]; 
    } 
    
  3. 从应用程序代理中删除managedObjectContext属性,并仅使用masterManagedObjectContext方法。这还需要明确定义_managedObjectContext实例变量。

+0

因此,我与第一步一起在App Delegate中将masterManagedObjectContext重命名为managedObjectContext,现在错误消失了。但表格视图控制器仍然是空白的。 – thebusiness11

+0

当你调试它时发现了什么?另外,你还在'numberOfSectionsInTableView:'中返回'0'吗?这将确保一个空白表视图:) –

+0

此外 - 我创建了一个聊天频道http://chat.stackoverflow.com/rooms/36417/thebusiness11-should-join-this-room随时加入我会尽力尽我所能帮助你 –

相关问题