NSArrayController addObject возвращает ноль

У меня есть основное приложение данных с двумя NIB, главное окно с парой NSTableView и форма для добавления контента. Форма имеет NSTextView и NSTextField. У меня есть два объекта в основных данных, и я управляю контентом с помощью двух NSArrayController. С одним NSArrayController следующий код в моем AppDelegate отлично работает для добавления контента:

    id o = [bookController newObject];
    [o setValue:@"Drafts" forKey:@"bookName"];
    [o setValue:0 forKey:@"sortOrder"];
    [bookController addObject:o];

Но этот код в моем классе AppController всегда возвращает значение null:

NSObject *o = [chapterArrayController newObject];

[o setValue:contentOfchapter forKey:@"chapterText"];
[o setValue:chapterTitleString forKey:@"chapterTitle"];
[o setValue:@"Drafts" forKey:@"bookChapter"];
NSLog(@"Where is the object?: %@", o);
[chapterArrayController addObject:o];

Кажется, что ChapterArrayController не связан с сущностью Chapter в основных данных, но привязки в IB верны. Я думаю, что это как-то связано с несколькими перьями, но здесь я немного в растерянности.

Любые указатели в правильном направлении приветствуются.

Спасибо.

Обновление 2: я создал класс с именем JBAdChapter, который выглядит так:

JBAAddChapter.h

#import <Cocoa/Cocoa.h>


@interface JBAddChapter : NSObject {

IBOutlet NSArrayController *bookController;
IBOutlet NSArrayController *chapterArrayController;

}
- (IBAction)testArrayControllers:(id)sender;
+ (void)getChapterData:(NSString *)passedChapterTitle withChapterText:(NSString *)passedChapterText;
- (void)standAloneTestArrayControllers;

@end

JBAAddChapter.m

#import "JBAddChapter.h"


@implementation JBAddChapter


+ (void)getChapterData:(NSString *)passedChapterTitle withChapterText:(NSString *)passedChapterText;
{
    [[self alloc] standAloneTestArrayControllers];
}


- (IBAction)testArrayControllers:(id)sender
{
    [self standAloneTestArrayControllers];
}

- (void)standAloneTestArrayControllers
{
    [chapterArrayController fetchWithRequest:nil merge:NO error:nil];
    NSLog(@"1. chapterArrayController %@", chapterArrayController);

    NSArray *a = [chapterArrayController arrangedObjects];
    NSLog(@"2. NSArray a = %@", a);

    NSUInteger numberOfMenuItems = [a count];
    NSLog(@"3. Count of items in array: %d", numberOfMenuItems);

    [bookController fetchWithRequest:nil merge:NO error:nil];
    NSLog(@"1. bookController %@", chapterArrayController);

    NSArray *b = [chapterArrayController arrangedObjects];
    NSLog(@"2. NSArray b = %@", b);

    NSUInteger newNumberOfMenuItems = [a count];
    NSLog(@"3. Count of items in array: %d", newNumberOfMenuItems);
}
@end

Я создал две кнопки в IB в своем главном окне и подключил одну к IBAction testArrayControllers выше. Другая кнопка, которую я подключаю к AppController и этому IBAction:

- (IBAction)testArrayControllers:(id)sender
{
    [JBAddChapter getChapterData:nil withChapterText:nil];
}

Если я вызываю standAloneTestArrayControllers из IBAction JBAdChapter, все работает нормально. Если я вызову тот же метод из AppController, используя фабричный метод в JBAdChapter, контроллеры массива равны нулю.

2010-01-07 06:15:36.971 Scout[3881:a0f] 1. chapterArrayController <NSArrayController: 0x200060b40>[entity: Chapter, number of selected objects: 1]
2010-01-07 06:15:36.972 Scout[3881:a0f] 2. NSArray a = (
loads of stuff
)
2010-01-07 06:15:36.973 Scout[3881:a0f] 3. Count of items in array: 9
2010-01-07 06:15:36.974 Scout[3881:a0f] 1. bookController <NSArrayController: 0x200060b40>[entity: Chapter, number of selected objects: 1]
2010-01-07 06:15:36.978 Scout[3881:a0f] 2. NSArray b = (
loads of stuff
)
2010-01-07 06:15:36.979 Scout[3881:a0f] 3. Count of items in array: 8
2010-01-07 06:15:38.402 Scout[3881:a0f] 1. chapterArrayController (null)
2010-01-07 06:15:38.402 Scout[3881:a0f] 2. NSArray a = (null)
2010-01-07 06:15:38.402 Scout[3881:a0f] 3. Count of items in array: 0
2010-01-07 06:15:38.403 Scout[3881:a0f] 1. bookController (null)
2010-01-07 06:15:38.403 Scout[3881:a0f] 2. NSArray b = (null)
2010-01-07 06:15:38.403 Scout[3881:a0f] 3. Count of items in array: 0

Итак, почему контроллеры массива должны возвращать nil из одного метода, а не из другого? Насколько я могу судить, все привязки в IB верны.


person Jon Buys    schedule 06.01.2010    source источник
comment
Вы должны использовать NSUInteger для возвращаемого значения count. int слишком короткий на 64-битных машинах и неправильная подпись (значения могут быть отрицательными, что не имеет смысла для подсчета вещей).   -  person Peter Hosey    schedule 06.01.2010
comment
Спасибо, Питер, я сделал предложенную вами настройку.   -  person Jon Buys    schedule 06.01.2010


Ответы (3)


Является ли ChapterArrayController нулевым, когда вы запрашиваете у него объект?

Вы говорите, что у вас есть два пера... создан ли экземпляр ChapterArrayController в этом втором пера? Если да, то загрузился ли перо к моменту вызова newObject?

person MyztikJenz    schedule 06.01.2010
comment
Что ж, я заставляю главуArrayController загружаться с помощью: [chapterArrayController fetchWithRequest:nil merge:NO error:nil]; и у меня ChapterArrayController привязан к объекту NSArrayController с привязками в обоих перьях. NSArray a = [chapterArrayController аранжированные объекты] int b = [количество]; NSLog (@элементы в массиве: %d, b); Приведенное выше int b всегда равно 0, и если я попытаюсь сделать это: NSObject *o = [chapterArrayController newObject]; NSLog(@Где находится объект: %@, o); NSLog будет регистрировать null. - person Jon Buys; 06.01.2010
comment
Если при вызове fetchWithRequest:merge:error: ChapterArrayController равен нулю, ничего не произойдет. Я предполагаю, что главаArrayController — это ivar IBOutlet, да? Попробуйте поставить: NSLog( @controller: %@, ChapterArrayController ); сразу после вашего запроса на получение. Я думаю, что он вернет ноль. Можете ли вы показать код, который загружает второй наконечник (тот, на который ссылается главаArrayController)? - person MyztikJenz; 06.01.2010
comment
MyztikJenz: Если бы chapterArrayController было nil, запрос arrangedObjects вернул бы nil. Запрос nil вместо count вернет 0. Он говорит, что count возвращает ненулевое значение; поэтому chapterArrayController не nil. - person Peter Hosey; 06.01.2010
comment
Питер: Мой ChapterArrayController возвращает (null) при отправке в NSLog. Я просто в недоумении, почему он это делает. NSLog(@"Chapter Array Controller %@", chapterArrayController); - person Jon Buys; 06.01.2010
comment
Вы уверены, что chapterArrayController подключен к наконечнику? Ваш код выглядит так, как будто он должен работать нормально. Тот факт, что вы можете нажать кнопку для запуска saveChapter:, говорит о том, что перо загружено, но любопытно, почему этот ivar равен нулю. - person MyztikJenz; 06.01.2010
comment
Да, привязки правильные в IB. Я мог бы просто пойти другим путем и использовать контекст управляемого объекта для добавления данных и обхода контроллера массива. - person Jon Buys; 07.01.2010
comment
Джон Байс: Хорошо, это не согласуется с вашими словами о том, что count возвращает значения «выше равно 0 каждый раз». [[nil arrangedObjects] count] == 0 для каждой поддерживаемой в настоящее время архитектуры. Где вы пытались зарегистрировать chapterArrayController? Возможно, вы зарегистрировали его до того, как загрузили перо. В любом случае, если ваш выход контроллера просто не подключен (и, следовательно, nil) или что-то еще не так, вы должны найти и устранить эту проблему, прежде чем пытаться сделать что-то еще. - person Peter Hosey; 07.01.2010

[[self alloc] standAloneTestArrayControllers];

Никогда не делайте этого. Всегда инициализируйте экземпляр, отправляя ему сообщение init (или initWithSomethingElse:, в зависимости от инициализаторов, предоставляемых классом). Если вы отправите какое-либо другое сообщение только что выделенному, но еще не инициализированному экземпляру, результаты будут неопределенными и почти наверняка неправильными.

[bookController fetchWithRequest:nil merge:NO error:nil];
NSLog(@"1. bookController %@", chapterArrayController);

Вы уверены, что не хотите регистрировать здесь bookController, а не chapterArrayController?

Если я вызываю standAloneTestArrayControllers из IBAction JBAdChapter, все работает нормально. Если я вызову тот же метод из AppController, используя фабричный метод в JBAdChapter, контроллеры массива равны нулю.

Потому что ты еще не зарядил перо. Ни вы не загрузили объект главы из пера, ни объект главы не загрузил сам кончик, ни что-либо явно (как в setChapterArrayController:) предоставило объекту главы контроллер массива для хранения.

Он работает из метода действия, потому что в этом контексте вы загрузили перо.

Итак, почему контроллеры массива должны возвращать nil из одного метода, а не из другого?

Контроллеры массива не возвращают nil; они не существуют. (Более того, функции и методы возвращают значения, а не объекты или классы.) Переменные, которые вы создали для хранения контроллеров массива, содержат nil, потому что вы не поместили туда никаких контроллеров массива.

Предполагая, что JBAdChapter должен владеть листом добавления главы, он должен загрузить перо (или создать экземпляр оконного контроллера) в своем методе init, и вы должны либо создать объект от владельца вашего главного окна (и сделать так, чтобы этот объект владел добавлением -chapter и использовать только тот объект add-chapter, которым он владеет) или сделать объект add-chapter одноэлементным. Первое легче.

И, конечно же, когда вы создаете этот или любой другой объект, вы должны всегда использовать пару alloc + init/initWith… (или предоставленный удобный метод автоматического освобождения); в противном случае, как и сейчас, ваш объект не загрузит свой наконечник, потому что вы никогда не отправляли ему сообщение init.

person Peter Hosey    schedule 07.01.2010

Думаю, я отвечу на свой вопрос здесь. Что-то было не так в моем NIB, и как только я удалил свои контроллеры массива и снова подключил их в IB, все снова заработало автоматически.

person Jon Buys    schedule 07.01.2010
comment
Знаешь, я видел это раньше. Единственный другой вариант, который я нашел, который работал (и только в некоторых случаях), — это сохранять перья как xibs или наоборот. Баг в ИБ? Мне никогда не удавалось надежно воспроизвести его. - person MyztikJenz; 08.01.2010