I don't know from the information provided why your generic init is being 
called, but the name of the class, AppController, is a clue to me. I'd expect a 
class called AppController to have a single instance, which would control the 
whole app, not to be a class that represents data in documents. My guess is 
you've been following along some examples for a non-document-based app and 
instantiated this in your xib based on those. You wouldn't want to do that for 
document data.

Set a breakpoint on the generic init function and your initWithCoder: is the 
self pointer in the debugger the same or different when you break at these 
points?

For document data, you almost certainly don't want to call that class 
AppController. Instead, call it what the data represents. Eg. Employee (in this 
case, TestData or whatever). I suspect your trouble is in the MyDocument class 
and how it manages the data object (currently AppController).

There are a few problems with your initWithCoder. It shouldn't call 
initWithString. It *should* call super init (or [super initWithCoder:coder] if 
the super class conforms to NSCoding, or the super classes designated 
initializer if it doesn't).

Here's what I think it should look like:

-(id)initWithCoder:(NSCoder *)coder
{
     if (self = [super init])
     {          NSLog(@"initWithCoder is being called");

          self.theString = [coder decodeObjectForKey:@"theString"];
          NSLog(@"theString is %@", self.theString);
     }
     return self;
}

(If you don't like dot notation use setTheString.)

Some other issues with your code:

You should implement dealloc and call self.theString = nil to release theString.

Read about designated initializers:
http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html#//apple_ref/doc/uid/TP30001163-CH22-SW8

Usually the longest initializer is the designated initializer. Your init method 
should call initWithString with a default string value (eg. [self 
initWithString:@"untitled"]).

Your initWithString is technically correct but not idiomatic. The usual pattern 
is as I showed initWithCoder, above. It's best to avoid multiple return paths 
in general, especially in init methods. Also, you might as well use your 
synthesized setter for theString, which will do the retain for you (eg. 
self.theString = aString).

Finally, you forgot to release the old theString and retain the new string in 
displayString. Again, just use your nice, convenient, synthesized setter, and 
it'll do that housekeeping for you. You'd then also want to remove the 
willChangeValueForKey and didChangeValueForKey calls, since the setter also 
does that for you.

If you don't have it, I highly, highly recommend getting a copy of Cocoa 
Programming for Mac OS X by Aaron Hillegass. It's well worth the money, and 
it's a lot easier to learn from than the free online documentation available.

Gunnar


----- Original Message ----
> From: Gabriel Roth <gabe.r...@gmail.com>
> To: Cocoa-dev@lists.apple.com
> Sent: Monday, May 11, 2009 12:42:01 PM
> Subject: beginner's question: having problems with saving/loading
> 
> In my attempt to learn Cocoa programming, I’m working on a tiny app to
> practice saving and loading files. Each document window contains a
> text field, a label, and a button. The user types a string into the
> text field and clicks the button, and the same text appears in the
> label. When the document is saved and reopened, the string that was
> saved with the document should appear in the label. Apart from saving
> and loading, the program works as I expect.
> 
> The app contains just one class (besides MyDocument), called
> AppController. The code for AppController is pasted below, followed by
> console output.
> 
> When loading a saved document, the application calls initWithCoder.
> This decodes the saved string and uses it in the initWithString
> method. According to log statements, the initWithString method is
> called successfully. But then the program calls the generic init
> method, which sets the string to NULL, so the label in the window
> reverts to the null placeholder set in the xib file.
> 
> I don’t know what’s calling the generic init method, or how to prevent
> this from happening, or if I should be avoiding this problem some
> other way. Any explanation of this situation would be appreciated.
> 
> === AppController.h ===
> #import 
> 
> 
> @interface AppController : NSObject {
>     NSString *theString;
>     IBOutlet NSTextField *theInput;
> }
> 
> @property (retain) NSString *theString;
> -(IBAction)displayString:(id)sender;
> -(id)initWithString:(NSString *)aString;
> 
> @end
> 
> === AppController.m ===
> #import "AppController.h"
> 
> @implementation AppController
> @synthesize theString;
> 
> -(IBAction)displayString:(id)sender
> {
>     NSLog(@"displayString is being called");
>     [self willChangeValueForKey:@"theString"];
>     theString = [theInput stringValue];
>     [self didChangeValueForKey:@"theString"];
> }
> 
> -(void)encodeWithCoder:(NSCoder *)coder
> {
>     [coder encodeObject:theString forKey:@"theString"];
> }
> 
> -(id)initWithCoder:(NSCoder *)coder
> {
>     NSString *aString = [[coder decodeObjectForKey:@"theString"] retain];
>     NSLog(@"initWithCoder is being called");
>     NSLog(@"aString is %@", aString);
>     [self initWithString:aString];
>     return self;
> }
> 
> -(id)initWithString:(NSString *)aString
> {
>     if (self = [super init]) {
>         NSLog(@"initWithString is being called with string %@", aString);
>         [self willChangeValueForKey:@"theString"];
>         theString = aString;
>         [theString retain];
>         [self didChangeValueForKey:@"theString"];
>         NSLog(@"theString is %@", theString);
>         return self;
>     }
>     else
>         return nil;
> }
> 
> -(id)init
> {
>     NSLog(@"generic init is being called");
>     self = [super init];
>     return self;
> }
> @end
> 
> === console output from opening a file ===
> 
> 2009-05-11 15:40:13.210 SaveTest2[26335:10b] readFromData called
> 2009-05-11 15:40:13.211 SaveTest2[26335:10b] initWithCoder is being called
> 2009-05-11 15:40:13.212 SaveTest2[26335:10b] aString is foo
> 2009-05-11 15:40:13.212 SaveTest2[26335:10b] initWithString is being
> called with string foo
> 2009-05-11 15:40:13.212 SaveTest2[26335:10b] theString is foo
> 2009-05-11 15:40:13.215 SaveTest2[26335:10b] generic init is being called
> 2009-05-11 15:40:13.217 SaveTest2[26335:10b] windowControllerDidLoadNib called
> _______________________________________________
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/tonecluster%40yahoo.com
> 
> This email sent to toneclus...@yahoo.com




_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to