Re: replacing self in initWithCoder method?
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.