NSArrayController addObject Returns null
I have a core data application with two NIBs, the main window with a pair of NSTableViews and a form for adding content. The form has an NSTextView and an NSTextField. I have two entities in core data, and manage the content with two NSArrayControllers. With one NSArrayController, the following code in my AppDelegate works fine for adding content:
id o = [bookController newObject];
[o setValue:@"Drafts" forKey:@"bookName"];
[o setValue:0 forKey:@"sortOrder"];
[bookController addObject:o];
But, this code in my AppController class always returns 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];
It seems like the chapterArrayController is not connected to the Chapter entity in core data, but the bindings in IB are correct. I'm thinking that this has something to do with the multiple nibs, but I'm kind of at a loss here.
Any pointers in the right direction are appreciated.
Thanks.
Update 2: I created a class named JBAddChapter, which looks like this:
JBAddChapter.h
#import <Cocoa/Cocoa.h>开发者_C百科;
@interface JBAddChapter : NSObject {
IBOutlet NSArrayController *bookController;
IBOutlet NSArrayController *chapterArrayController;
}
- (IBAction)testArrayControllers:(id)sender;
+ (void)getChapterData:(NSString *)passedChapterTitle withChapterText:(NSString *)passedChapterText;
- (void)standAloneTestArrayControllers;
@end
JBAddChapter.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
I've created two buttons in IB in my main window, and hooked one up to the testArrayControllers IBAction above. The other button I hook up to AppController and this IBAction:
- (IBAction)testArrayControllers:(id)sender
{
[JBAddChapter getChapterData:nil withChapterText:nil];
}
If I call the standAloneTestArrayControllers
from JBAddChapter's IBAction, everything works fine. If I call that same method from AppController using the a factory method in JBAddChapter, I the array controllers are nil.
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
So, why would the array controllers be returning nil from one method, but not the other? All bindings in IB are correct, as far as I can tell.
Is chapterArrayController nil when you ask it for an object?
You say you have two nibs... is chapterArrayController instantiated in that second nib? If so, has the nib been loaded by the time newObject is called?
[[self alloc] standAloneTestArrayControllers];
Never ever do this. Always initialize the instance by sending it an init
(or initWithSomethingElse:
, depending on the initializers the class provides) message. If you send any other message to a freshly-allocated-but-not-yet-initialized instance, the results are undefined and almost certainly wrong.
[bookController fetchWithRequest:nil merge:NO error:nil]; NSLog(@"1. bookController %@", chapterArrayController);
Are you sure you don't mean to log bookController
here, not chapterArrayController
?
If I call the standAloneTestArrayControllers from JBAddChapter's IBAction, everything works fine. If I call that same method from AppController using the a factory method in JBAddChapter, I the array controllers are nil.
Because you haven't loaded the nib yet. Neither have you loaded the chapter object from a nib, nor the chapter object loaded a nib itself, nor anything explicitly (as in setChapterArrayController:
) given the chapter object an array controller to hold on to.
It works from the action method because in that context, you have loaded the nib.
So, why would the array controllers be returning nil from one method, but not the other?
The array controllers are not returning nil
; they don't exist. (Moreover, functions and methods return values, not objects or classes.) The variables you've created to hold array controllers hold nil
because you have not put any array controllers there.
Assuming that JBAddChapter is meant to own the add-chapter sheet, it should load the nib (or instantiate a window controller) in its init
method, and you should either create the object from your main window's owner (and have that object own the add-chapter object, and only ever use the add-chapter object that it owns) or make the add-chapter object a singleton. The former is easier.
And, of course, when you create this object or any other, you must always use the alloc
+ init
/initWith…
pair (or provided autoreleasing convenience method); otherwise, as now, your object will not load its nib because you never sent it an init
message.
Guess I'll answer my own question here. Something was wrong in my NIB, and once I deleted my array controllers, and reconnected them in IB, everything just automagically worked again.
精彩评论