• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: replacing self in initWithCoder method?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: replacing self in initWithCoder method?


  • Subject: Re: replacing self in initWithCoder method?
  • From: Chris Kane <email@hidden>
  • Date: Thu, 5 Dec 2002 12:14:44 -0800

The following discussion may or may not apply to this particular problem

It is not particularly safe to try to replace objects in initWithCoder:, because objects which have already gotten a pointer to the object being replaced don't get their pointer value updated to the new return value. That previous sentence probably doesn't make sense on one reading, so re-read it if necessary and let me give an example. This example is not necessarily the exact problem you're dealing with, but rather serves to illustrate the "unsafeness". (And it applies to either old-style typedstream archiving or keyed archiving.)

Say NSViews archive their subviews, and a reference back to their superview.
Let's imagine a view V is getting unarchived. NSView's initWithCoder: gets
invoked early on in a subclass's initWithCoder: via the super chaining. The
unarchiver allocates a new view of type archived-class-of(V), names it "V"
for identification purposes, and invokes -initWithCoder: on the new view.
Up the super chain we go. NSView unpacks the subviews one at a time,
which creates the new objects and causes them to unarchive (recursively).
Each subview of V unpacks its own subviews and unpacks the reference
to its superview (V), by asking for "V", and getting from the unarchiver a
pointer to half-initialized V, because remember, somewhere up the call
stack we're in the middle of V's -initWithCoder:. The subviews don't invoke
any methods on V, so it doesn't much matter that it is half-initialized; but
all these subviews now have a pointer to the "original" V which was sent
-initWithCoder:, and nothing is going to fix them up later if V's initWithCoder:
returns a "new" object.

There was a discussion of this last year about October 10 on this list with subject "Persistence", that you can look up in the archives. This issue can be fixed, with additional architecture, and effort from objects which want to be archivable. The conclusion in the discussion and internally that it wasn't worth the complexity to fix.

Replacing the views later will be a better plan. "Fixing up" the window after the entire window/nib is unarchived by exchanging the combo boxes if necessary would seem to be safest, which is easy enough if you have an outlet to each combo box.


Chris Kane
Cocoa Frameworks, Apple


On Tuesday, December 3, 2002, at 12:22 PM, Dan Wood wrote:

Hmm, I've tried to create my own object and just copy over the attributes of the object that was decoded into a new object. But further up the calling chain, things "hang" in nib-decoding code that I don't know what is doing. Any other ideas?

Code snippet so far is:

- (id)initWithCoder:(NSCoder *)decoder
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL beTextField = [defaults boolForKey:@"UsePlainTextField"];

if (beTextField)
{
self = [super initWithCoder:decoder]; // first decode the original combo box object

NSTextField *newField = [[NSTextField alloc] initWithFrame:[self frame]];

[newField setAllowsEditingTextAttributes:[self allowsEditingTextAttributes]];
[newField setBackgroundColor:[self backgroundColor]];
[newField setBezelStyle:[self bezelStyle]];
[newField setBezeled:[self isBezeled]];
[newField setBordered:[self isBordered]];
[newField setDelegate:[self delegate]];
[newField setDrawsBackground:[self drawsBackground]];
[newField setEditable:[self isEditable]];
[newField setImportsGraphics:[self importsGraphics]];
[newField setSelectable:[self isSelectable]];
[newField setTextColor:[self textColor]];

[self autorelease]; // no longer needing the "old" self
self = (id)newField; // replace self with the object we created
}
else
{
if (self = [super initWithCoder:decoder])
{
... subclass-specific encoding
}
}
return self;
}




FROM: Jirtme Laurens
DATE: 2002-11-28 09:27

Le mercredi, 27 nov 2002, ` 21:54 Europe/Zurich, Dan Wood a icrit :

> I have some UI elements in a nib that are subclasses of NSComboBox --
> however, I would like to, via a preference, just show them as a plain
> NSTextField instead. (NSTextField happens to be a subclass of
> NSComboBox.)
>
> I'm thinking that maybe I can fake this in the initWithCoder: method
> of MyComboBox, so that if the preference is set to use a plain
> NSTextField instead, I replace self with an NSTextField.
>
> However, it's not working (I end up seeing a combo box in the
> interface, though it doesn't respond to the popup button. And, I get
> this message at runtime when the NSTextField is built:
>
> NSView not correctly initialized. Did you forget to call super?
>
> Am I doing this wrong? Any suggestions on making this work?
>
> Dan
>
>

As far as I understand, the format of the data in the coder is severely
tied to the class that created the archive. So,
you should always call -[NSComboBox initWithCoder:]. Once the combo box
is inited, you can decide to use it as is or just make a NSTextField
poor man clone.

BTW, this is weird design: NSComboBox is a subclass of NSTextField, not
the converse

--
Dan Wood
Karelia Software, LLC
email@hidden
http://www.karelia.com/
Watson for Mac OS X: http://www.karelia.com/watson/
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

References: 
 >Re: replacing self in initWithCoder method? (From: Dan Wood <email@hidden>)

  • Prev by Date: Re: experts : is performSelectorOnMainThread blocking ?
  • Next by Date: runtime error using NSArray with NSButton
  • Previous by thread: Re: replacing self in initWithCoder method?
  • Next by thread: Printing many, many pages efficiently
  • Index(es):
    • Date
    • Thread