views:

178

answers:

3

Background: I'm a .NET guy who has no prior experience in Objective-C/Cocoa, but I'm working through Aaron Hillegass' book, "Cocoa Programming for Mac OS X" trying to pick up the basics. (Great book so far, BTW!) For the purpose of completing one of the optional side challenges, I'm writing a document-based app that lets users draw ovals in arbitrary locations.

I have two classes, interfaces as follows:

@interface OvalDrawDocument : NSDocument
{
    IBOutlet OvalView* myOvalView;
}
@end

@interface OvalView : NSView {
    NSMutableArray *ovals;
}
@property (readwrite, assign) NSMutableArray *ovals;
@end

In the implementation of OvalDrawDocument I'm trying to use the auto-generated property accessor for ovals like so:

// in OvalView.m
@synthesize ovals;

// in OvalDrawDocument.m
[myOvalView setOvals:loadedOvals];                // setter?
NSMutableArray *ovalsToSave = [myOvalView ovals]; // getter?

However, the compiler warns me that the methods aren't found, and they don't work at runtime either. They appear in Code Sense, but I guess that doesn't really mean anything (Still getting used to the differences between XCode/VS here) I'm guessing there's some Obj-C concept I'm not quite grasping here, possibly related to the fact that myOvalView is also an IBOutlet, but I'm pretty lost. What should I be doing, and more importantly, why?


Update: I didn't declare OvalView.h in OvalDrawDocument.m. Doing so fixed the compilation warnings. However, saving and loading still don't seem to work and I can't figure out why.

As requested, I've posted the full source code online for perusal: Browse or Download (59KB zip).

+5  A: 

The warning: Import OvalView's header in the OvalDrawDocumentation implementation file.

The messages not working at runtime: Make sure you have actually connected the outlet in IB.

Also, as Martin Pilkington said in his comment on your question, you probably should declare that property with retain, not assign.

Peter Hosey
If the calls don't work at runtime, then that can't be the (only) problem.
smorgan
Good point. Edited accordingly.
Peter Hosey
Importing the header fixed the warnings. The outlet is properly connected in IB to the best of my knowledge -- I'll post the full source to be sure.
Brant Bobby
Yes, the outlet is connected, and saving and loading appear to mostly work. Two problems you do have are: 1. You've not declared any real type information in Info.plist, so the file saves with extension “????”; 2. Probably for the same reason, the Dock does not recognize that I can drop that file onto your app to open it. Also, you're not adding undo actions to the document's undo manager. This causes two more problems: 1. I can't undo (obviously). 2. The change count doesn't get updated, so the dirty dot doesn't appear in the close box.
Peter Hosey
The reason why you don't see the ovals in the oval view is that nib loading happens *after* document loading (after all, which one's more likely to fail?). More conceptually, your document (which is primarily a controller) is expecting the view to hold onto its model for it, but that's the controller's job. Move the ovals array to the document class. It's OK to let the view have a copy, but primary responsibility for holding the model rests with the controller, which is your document.
Peter Hosey
+1  A: 

It has nothing to do with the IBOutlet keywrod, which is simply a "helper" keyword for Interface Builder and is defined as "nothing" at compile time. You did import the relevant header files and did an alloc/init on myOvalView?

tmadsen
Why would you do alloc/init if the view already exists in the nib?
Peter Hosey
It may exist in the nib file without having been allocated and initiated, you're looking for [[zzz alloc] initWithNib:@"nib name here"];
tmadsen
NSView has no initWithNib: method.
Peter Hosey
oh sry, I was confusing NSView with NSViewController, my bad.
tmadsen
A: 

I think you're going to have to show more of the code, since you appear to have the right things there, so you must be missing something somewhere else. Also, if you're going to declare ovals as a property, then it would make sense to use the property syntax in OvalDrawDocument:

// in OvalDrawDocument.m
myOvalView.ovals = loadedOvals;                // setter
NSMutableArray *ovalsToSave = myOvalView.ovals; // getter
Mark Bessey