Как загрузить Core Data в другое представление, кроме RootViewController? - PullRequest
3 голосов
/ 13 февраля 2011

У меня в основном есть основные данные и приложение работает правильно, за исключением кода в AppDelegate.Код, с которым у меня возникают проблемы, следующий:

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

    RootViewController *tableController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
    tableController.managedObjectContext = [self managedObjectContext];

    self.navigationController = [[UINavigationController alloc] initWithRootViewController:tableController];
    [tableController release];

    [window addSubview: [self.navigationController view]];
    [window makeKeyAndVisible];

}

Я не хочу делать managedObjectContext контроллером корневого представления при запуске.Я хочу сделать это другим контроллером представления.Однако, если я изменяю классы на контроллер представления, для которого он мне нужен, он загружает этот контроллер представления при запуске приложения, а это не то, что я хочу делать.Я все еще хочу запустить корневое представление, но хочу загрузить контекст основных данных для моего другого контроллера представления.Я действительно запутался в том, как решить эту проблему.Я потратил 2 дня, пытаясь найти способ исправить это, но пока не повезло.Буду признателен за любую помощь.

Кроме того, если я пропущу следующее в appdelegate didfinishlaunching:

RootViewController *tableController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
        tableController.managedObjectContext = [self managedObjectContext];

        self.navigationController = [[UINavigationController alloc] initWithRootViewController:tableController];
        [tableController release];

Я получаю эту ошибку:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Hello'

EDIT:Вот код сущности:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"Lap Times";

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addTime:)];
    self.navigationItem.rightBarButtonItem = addButton;
    [addButton release];

    [self fetchRecords];

}

- (void)addTime:(id)sender {

    addTimeEvent *event = (addTimeEvent *)[NSEntityDescription insertNewObjectForEntityForName:@"addTime" inManagedObjectContext:self.managedObjectContext];
    [event setTimeStamp: [NSDate date]];

    NSError *error;
    if (![managedObjectContext save:&error]) {
        // This is a serious error saying the record could not be saved.
        // Advise the user to restart the application
    }

    [eventArray insertObject:event atIndex:0];
    [self.tableView reloadData];

}

- (void)fetchRecords {

    // Define our table/entity to use
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"addTime" inManagedObjectContext:self.managedObjectContext];

    // Setup the fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];

    // Define how we will sort the records
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    [request setSortDescriptors:sortDescriptors];
    [sortDescriptor release];

    // Fetch the records and handle an error
    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

    if (!mutableFetchResults) {
        // Handle the error.
        // This is a serious error and should advise the user to restart the application
    }

    // Save our fetched data to an array
    [self setEventArray: mutableFetchResults];

    [mutableFetchResults release];
    [request release];

}

Также, если я использую свой собственный appdelegate с именем MyAppDelegate

MyAppDelegate *tableController = [[MyAppDelegate alloc] initWithStyle:UITableViewStylePlain];
tableController.managedObjectContext = [self managedObjectContext];

self.navigationController = [[UINavigationController alloc] initWithRootViewController:tableController];

, я получаю следующую ошибку:

Object cannot be set- either readonly property or no setter found

Ответы [ 3 ]

0 голосов
/ 13 февраля 2011

Я не вижу проблемы с оригинальным подходом, который вы используете? По сути, вы создаете managedObjectContext в своем делегате приложения и передаете его tableController через назначение.

Альтернативный способ сделать это состоит в том, чтобы ваш viewController «запросил» managedObjectContext от делегата приложения. Таким образом, вы по-прежнему будете размещать ваши методы CoreData в вашем AppDelegate и использовать следующее, где вы хотите получить ссылку на контекст. Поскольку managedObjectContext лениво загружается по запросу, он будет создан только при первом обращении к методу managedObjectContext в делегате приложения.

AppDelegate *theDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = theDelegate.managedObjectContext;

PS1: очевидно, вам нужно заменить AppDelegate на правильное имя для вашего приложения.

PS2: причина, по которой вы получаете ошибку при внесении изменений, заключается в том, что у CoreData нет контекста, с которым можно работать.

0 голосов
/ 13 февраля 2011

если вы получите исключение для +entityForName:, вы должны разместить код около +entityForName:.

Если бы мне пришлось сделать предположение, я бы сказал, что ваш код выглядит следующим образом:

entity = [NSEntityDescription entityForName:@"Hello" 
                     inManagedObjectContext:managedObjectContext];
                                            ^^^^^^^^^^^^^^^^^^^^

это означает, что вы используете managedObjectContext без метода получения.И геттер использует ленивую загрузку для загрузки контекста, если это необходимо в первый раз.
Могу поспорить, что managedObjectContext на данный момент равен нулю.Используйте отладчик, чтобы проверить это.

А затем измените строку следующим образом:

entity = [NSEntityDescription entityForName:@"Hello" 
                     inManagedObjectContext:self.managedObjectContext];
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^

Код работает, когда вы включаете четыре строки о контроллере rootview из-за этого вызова:

tableController.managedObjectContext = [self managedObjectContext];
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^

thisсоздаст контекст, если он равен нулю.Ленивая загрузка.

[self managedObjectContext] - это то же самое, что и self.managedObjectContext

, но все в моем посте является предположением, потому что вы не включили код в + entityForName: inManagedObjectContext:

0 голосов
/ 13 февраля 2011

В названии RootViewController нет ничего волшебного. Вы можете переименовать его или обменять его с любым другим View Controller, если эти View Controller настроены правильно. Возможно, вы захотите взять RootViewController и настроить свой новый View Controller соответственно.

Тем не менее я не понимаю, что вы хотите сделать. Возможно, вы захотите опубликовать код, который не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...