CarArrayController never initialized?


#1

Hi there,
I’ve just finishing creating the CarArrayController class. I tried overriding the newObject method, and setting the array controller in the .xib file as class CarArrayController (yes, in the Identity Inspector). First, I was not getting a date set to the current time. I decided to try logging the method to see if it ever got called, and sure enough, it did not. Secondly, however, I put in an override for the init method of CarArrayController. The only thing I did was to log if it ever got called. It never did either. I have double and triple checked that they array controller is of type CarArrayController, but it is never initialized. The only other thing that may be relevant is to say that when I created the class, it did not give me any automatically generated method stubs as the book implies (Page 190, paragraph 2 - "In CarArrayController.m, remove the init and dealloc the template created…). It was a completely default .h/.m pair. Any ideas?

CarArrayController.h:

[code]#import <Cocoa/Cocoa.h>

@interface CarArrayController : NSArrayController

@end[/code]

CarArrayController.m:

[code]@implementation CarArrayController

  • (id)init
    {
    self = [super init];
    if (self) {
    NSLog(@“CarArrayController initialized”);
    }
    return self;
    }

@end[/code]
(Yes, I realize there is no newObject override here; I took that out in an attempt to isolate why the class is not being initialized).

The .xib file says, when the array controller is selected, under the Identity Inspector heading ‘Custom Class’ that it is of class CarArrayController.

Why in the world is it not being initialized?

Any help is appreciated :slight_smile:


#2

Just thought I’d add that when the add button is pressed, none of the log statements show up (as before), but I get a bunch of stuff in the debugger:

Debugger output on press of add button:

2012-12-30 21:26:26.233 CarLot[3075:303] -[NSManagedObject setObject:forKey:]: unrecognized selector sent to instance 0x100549770
2012-12-30 21:26:26.233 CarLot[3075:303] -[NSManagedObject setObject:forKey:]: unrecognized selector sent to instance 0x100549770
2012-12-30 21:26:26.235 CarLot[3075:303] (
0 CoreFoundation 0x00007fff8e2970a6 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff92a333f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8e32d6ea -[NSObject(NSObject) doesNotRecognizeSelector:] + 186
3 CoreFoundation 0x00007fff8e2855ce forwarding + 414
4 CoreFoundation 0x00007fff8e2853b8 _CF_forwarding_prep_0 + 232
5 CarLot 0x0000000100001c93 -[CarArrayController newObject] + 147
6 AppKit 0x00007fff90380074 -[NSArrayController _executeAdd:didCommitSuccessfully:actionSender:] + 69
7 AppKit 0x00007fff9071a36a _NSSendCommitEditingSelector + 58
8 AppKit 0x00007fff90418e24 -[NSController controllerEditor:didCommit:contextInfo:] + 190
9 CoreFoundation 0x00007fff8e28a63c invoking
+ 140
10 CoreFoundation 0x00007fff8e28a4d7 -[NSInvocation invoke] + 263
11 CoreFoundation 0x00007fff8e28a6a9 -[NSInvocation invokeWithTarget:] + 57
12 Foundation 0x00007fff92ca6db5 __NSFireDelayedPerform + 358
13 CoreFoundation 0x00007fff8e253da4 CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 20
14 CoreFoundation 0x00007fff8e2538bd __CFRunLoopDoTimer + 557
15 CoreFoundation 0x00007fff8e239099 __CFRunLoopRun + 1513
16 CoreFoundation 0x00007fff8e2386b2 CFRunLoopRunSpecific + 290
17 HIToolbox 0x00007fff95ce20a4 RunCurrentEventLoopInMode + 209
18 HIToolbox 0x00007fff95ce1d84 ReceiveNextEventCommon + 166
19 HIToolbox 0x00007fff95ce1cd3 BlockUntilNextEventMatchingListInMode + 62
20 AppKit 0x00007fff90127613 _DPSNextEvent + 685
21 AppKit 0x00007fff90126ed2 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
22 AppKit 0x00007fff9011e283 -[NSApplication run] + 517
23 AppKit 0x00007fff900c2cb6 NSApplicationMain + 869
24 CarLot 0x00000001000019f2 main + 34
25 libdyld.dylib 0x00007fff8b1a37e1 start + 0
)

It doesn’t throw any exceptions or do anything to the application that might be considered disruptive, but it might have something to do with the problem? I don’t really know.


#3

I think I found the problem…
#1: I should have been more clear; the debugger output came only when I reimplemented newObject. My new CarArrayController.m is below:

[code]#import “CarArrayController.h”

@implementation CarArrayController

  • (id)newObject
    {
    id newObj = [super newObject];
    NSDate *now = [NSDate date];
    [newObj setValue:now forKey:@“datePurchased”];
    NSLog(@“Current Date Set”);
    return newObj;
    }

@end[/code]
I just got intimidated by the huge debugger output, and failed to realize the first two lines: setObject:forKey:. Well that was exactly the problem. Upon taking out “[newObj setValue:now forKey:@“datePurchased”]” The debugger only gave me “Current Date Set”, the log statement, which is exactly what I needed. Can anyone shed some light on why cutting, running, then pasting back would have made a difference? I had tried deleting the whole method, as I wrote in my first post, to no avail, but simply taking out that one message send, then pasting it back, did the trick perfectly.

It works now, which I suppose is the main thing. But can anyone give me something to learn from this? Is Xcode just buggy, or am I missing something?

Thanks


#4

Sorry about this; I just had one more question though:
We made the target of the “Add” button the add: method of the array controller. I looked in the documentation, and found that newObject is only implemented because of NSObjectController, but no where can I find that it is called by the add: method. How did you know to override newObject and not add:? I know if I had been writing this, my first thought would have been to override add: in much the same way (call the superclass, then simply set the datePurchased key).


#5

Objective - C is a fairly amazing language, however to quote the great nerds that gave us this wonderful book, “With great power comes great responsibility”. Objective - C will let you send messages all day long at nil objects without you blowing up your code, its nice :smiley:. However the static analyzer used on the front end AST can not and will not warn you of every potential error “YET”; but it does warn you of most of them. However your code is going to be viewed by the analyzer as OK, I will get into that in a moment. If your message send syntax is potentially correct it will process it to the assembler, maybe other stuff depending on flags. The assembler is like a Union Worker in a Factory it will do its job exactly has been described to it and no more no less, in theory, it can not detect if the code is going to blow up at you it simply translates language via injective statements into hex. Ultimately the analyzer for whatever reason looked at your code and said “sure why not”.

Now what is the reason that led to this “Sure why not” from the analyzer, the fact of the matter is that the method [id setObject:(id *) forKey:(NSString *)] exists. So the compiler and xCodes native analyzer can not make the distinction “Thats a bad idea” it can only make the distinction “Thats an idea thats possible, maybe” or “That is impossible”. Your message because newObj was type id was not impossible, if you want to guard against that kind of thing well it would be rough but doable, way beyond the time to just learn from this :smiley: