Почему NSManagedObjectContext = nil после первой попытки получить его?

У меня есть NSOutlineView с пользовательским NSOutlineViewDataSource на основе отношения родитель-потомок или двух объектов базовые данные.

Я еще не нашел простого способа привязать их к представлению, поэтому сейчас я выясняю, как сообщить NSOutlineView об обновлении после того, как я вставлю новый объект в любую из сущностей и их соответствующие NSArrayControllers.

NSOutlineView нормально заполняется на awakeFromNib следующим образом:

rootNode = [[IFParentNode alloc] initWithTitle:@"Root" children:nil];
    NSInteger clientCounter;
    clientCounter = 0;
    NSFetchRequest *clientsFetchRequest = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *clientsMoc= [clientsController managedObjectContext];
    NSEntityDescription *clientsEntity = [NSEntityDescription entityForName:@"Clients" inManagedObjectContext:clientsMoc];
    [clientsFetchRequest setEntity:clientsEntity];
    //sort
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"clientCompany" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [clientsFetchRequest setSortDescriptors:sortDescriptors];
    NSError *clientsFetchError = nil;
    clientsArray = [clientsMoc executeFetchRequest:clientsFetchRequest error:&clientsFetchError];
    [clientsFetchRequest release];

    NSInteger projectCounter;
    projectCounter = 0;
    NSFetchRequest *projectsFetchRequest = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *projectsMoc= [projectsController managedObjectContext];
    NSEntityDescription *projectsEntity = [NSEntityDescription entityForName:@"Projects" inManagedObjectContext:projectsMoc];
    [projectsFetchRequest setEntity:projectsEntity];
    NSError *projectsFetchError = nil;
    projectsArray = [projectsMoc executeFetchRequest:projectsFetchRequest error:&projectsFetchError];
    [projectsFetchRequest release];

    for (NSString *s in clientsArray) {
        NSManagedObject *clientMo = [clientsArray objectAtIndex:clientCounter];  // assuming that array is not empty
        id clientValue = [clientMo valueForKey:@"clientCompany"];
        //NSLog(@"Company is %@", parentValue);

        IFParentNode *tempNode = [[IFParentNode alloc] initWithTitle:[NSString stringWithFormat:@"%@", clientValue] children:nil];

        clientCounter = clientCounter + 1;
        [rootNode addChild:tempNode];
        [tempNode release];
    }

    for (NSString *s in projectsArray) {
        NSInteger viewNodeIndex;
        viewNodeIndex = 0;
        NSManagedObject *projectMo = [projectsArray objectAtIndex:projectCounter];  // assuming that array is not empty
        id projectValue = [projectMo valueForKey:@"projectTitle"];
        id projectParent = [[projectMo valueForKey:@"projectParent"] valueForKey: @"clientCompany"];
        // find if theres an item with the projetParent name
        id nodeTitle = [[rootNode children] valueForKey:@"title"];
        for(NSString *companies in nodeTitle) {
            if([companies compare:projectParent] == NSOrderedSame) {
                //NSLog(@"Yeh! Company is %@ and parent is %@ and id is: %d", companies, projectParent, viewNodeIndex);
                // then assign that node to be the tempnode.
                IFParentNode *tempNode = [rootNode.children objectAtIndex:viewNodeIndex];
                IFChildNode *subTempNode = [[IFChildNode alloc] initWithTitle:[NSString stringWithFormat:@"%@", projectValue]];
                [tempNode addChild:subTempNode];
                [subTempNode release];
                [tempNode release];
            } else {
                // do nothing.
            }
            viewNodeIndex = viewNodeIndex + 1;
        }
        projectCounter = projectCounter + 1;
    }

    [outlineView expandItem:nil expandChildren:YES];

Я пытался вызывать этот же метод каждый раз, когда добавлял объект к любому объекту, думая, что он снова заполнит NSOutlineView с нуля. Вместо этого он просто выдает ошибку:

+entityForName: could not locate an NSManagedObjectModel for entity name 'Clients'

Журнал clientsMoc показывает, что он равен нулю каждый раз, когда я вызываю его после awakefromnib (для этого он отлично работает). Я видел несколько упоминаний об этом на этом сайте, но ссылки на себя или делегаты NSApp пока не работают для меня. Я не знаю, в каком направлении взять это? Мне нужно вернуть MOC, который не равен нулю.

Мой класс appdelegate является стандартным, настроенным для основных приложений данных.

Заранее спасибо!


person biscuitstack    schedule 12.03.2011    source источник


Ответы (2)


Ошибка, о которой вы сообщаете, не имеет ничего общего с планом. Это ошибка основных данных.

Либо у вас неправильное имя сущности, либо ваш контекст manageObject не был инициализирован или на него неправильно ссылаются.

person TechZen    schedule 13.03.2011
comment
Спасибо ТехЗен. Нет, сущность определенно существует (как я уже сказал, NSOutlineView нормально заполняется на awakeFromNib с включенным кодом). Только при вызове этого метода позже я получаю эту ошибку. Из более детективной работы я на 99% уверен, что это связано с manageObjectContext, но ни одно из рекомендуемых решений не помогает (например, сначала ссылаться на себя при цитировании MOC) или ответы, зависящие от iPhone. - person biscuitstack; 14.03.2011
comment
Просто добавлю: проверка для manageObjectContext = nil возвращается как nil, так что это, безусловно, та проблема, с которой я сталкиваюсь. У меня проблемы с тем, как ее решить. Я не уверен, какой аспект приведенного выше кода следует исключить или добавить, чтобы убедиться, что MOC загружается нормально при многократном вызове метода. Кроме того, я не уверен, почему он работает нормально при первом пробуждении, а затем отключается. - person biscuitstack; 14.03.2011
comment
Похоже, вы теряете ссылку на свой manageObjectContext. Я предполагаю, что это свойство некоторого класса, такого как делегат приложения. Убедитесь, что свойство сохраняет объект. Если вы передаете его свойству контроллера, убедитесь, что оно также сохраняется. Я отмечаю, что вы не используете средства доступа или справочную форму self.projectsMoc, так что это тоже может быть проблемой. - person TechZen; 15.03.2011
comment
В этом случае есть два manageObjectContexts, и они по отдельности являются свойствами класса clientsController и projectsController (если я правильно понимаю ситуацию - я все еще новичок в этом - я обращаюсь к ним с помощью eg[clientsController managedObjectContext]. Какой был бы лучший способ проверить что они сохраняют объект? Я не изменил свой исходный xcode, сгенерированный appDelegate для основных данных, поэтому код manageObjectContext для этого является стандартным, который генерирует xcode, если вы инициируете приложение с основными данными. - person biscuitstack; 15.03.2011
comment
У меня есть ощущение, что я могу неправильно понимать более высокий managedObjectContext за пределами managedObjectContext, о котором я думаю с каждым NSArrayController, например, когда я использую: NSManagedObjectContext *clientsMoc= [clientsController managedObjectContext]; - person biscuitstack; 15.03.2011
comment
Вы проверяете удержание, (1) проверяя определение свойства или (2) любой пользовательский метод установки/доступа, который вы используете. Я предполагаю, что оба контроллера получают свою индивидуальную ссылку на контекст от делегата приложения? Обычно, если у вас есть один контекст, все ссылки указывают на один и тот же объект. Если контроллер равен нулю, то вы, вероятно, неправильно назначили/сохранили его. - person TechZen; 15.03.2011
comment
Спасибо, что вернулись, TechZen. Я смог решить некоторые из проблем MOC, выяснив эквивалент решения для Mac, которое я видел несколько раз, чтобы решить эту проблему на iPhone. Если MOC равен нулю, добавьте эту строку: clientsMoc = [(nameofAppDelegate *)[[NSApplication sharedApplication] delegate] managedObjectContext];. Получение объектов массивов, полученных в результате выборки сущностей, показывает, что новые объекты были вставлены правильно и нашли свой путь вниз в массиве. Однако NSOutlineView не обновляется даже после перезагрузки данных с использованием приведенного выше кода? - person biscuitstack; 15.03.2011
comment
Если представление NSOutline не обновляется, то либо (1) оно неправильно привязано к контроллеру, либо (2) контроллер массива не возвращает правильные объекты при запросе, либо и то, и другое. Вы не можете использовать стандартный NSArrayController или группу NSArrayControllers для управления структурой, потому что контроллер массива не понимает иерархию данных. Вы должны использовать контроллер дерева, который понимает иерархию. Либо используйте NSTreeController, либо напишите свой собственный класс контроллера дерева, который воспроизводит поведение NSTreeController. Поскольку вы новичок, я рекомендую первое. - person TechZen; 15.03.2011
comment
Если вы не можете заставить NSTreeController работать, пропустите привязки и реализуйте NSOutlineViewDataSource Protocol в классе и управляйте таблицей напрямую. Это больше работы, но это намного надежнее, и вы действительно можете видеть, что происходит, вместо того, чтобы полагаться на невидимое наблюдение за ключом и значением, чтобы заставить все работать. - person TechZen; 15.03.2011
comment
Код, который я включил, предназначен для просмотра 2 NSArrayControllers, поиска определенных значений в каждом, которые относятся к атрибутам связанных сущностей, и сортировки их по родительским и дочерним узлам в layoutView на основе отношения родитель/потомок между ними, которое определено в объекты основных данных. Я написал для этого класс, который избегает NSTreeController, так как с ним это было невозможно. На самом деле, вопрос разветвился на то, почему мой layoutView не перезагружается, поэтому я задал для этого новый вопрос по адресу: stackoverflow.com/questions/5314463/ - person biscuitstack; 15.03.2011
comment
В моем коде моя информация фильтруется в два конечных массива (projectsArray и clientArray), прежде чем я зафиксирую эти два родительских или дочерних узла в моем layoutView. NSLog обоих из них показывает, что любые добавленные мной объекты правильно сохраняются в этих массивах. Я ввел новую информацию в разветвленный вопрос, который более актуален для этого. Поэтому я не уверен, правильно ли (2) в ваших возможных решениях. Я рассмотрю (1), но не вижу проблем с привязкой. Еще раз спасибо TechZen. - person biscuitstack; 15.03.2011

Я изо всех сил пытался исправить это, используя метод, который часто встречается в Google, включающий обращение к NSManagedObjectContext из appDelegate, которые всегда кажутся актуальными для iPhone. Я сделал версию кода для Mac по строкам:

clientsMoc = [(nameofAppDelegate *)[[NSApplication sharedApplication] delegate] managedObjectContext];

То, что было вызвано клиентамиMoc, оказалось нулевым. Приступая к фактическому ответу на мой вопрос, однако. Я не уверен на 100%, но я считаю, что в моем случае это могло быть связано с тем, что я непреднамеренно создал два экземпляра в своем классе, как указано здесь. Причина, по которой я думаю, что это может быть правдой, заключается в том, что я время от времени получал повторяющиеся ошибки в консоли. Позже мой контроллер изменился, поэтому этот вопрос стал неуместным для моего проекта.

person biscuitstack    schedule 18.03.2011