Overriding -copyWithZone: the right way
-
Hello all!
I have a subclass of NSCell (for a TableView) that is supposed to
display an image and an NSPopUpButtonCell. Everything works fine so
far, but I obviously need to override -copyWithZone:. Here's what I
came up with:
- (id)copyWithZone:(NSZone *)zone {
PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
initImageCell:nil];
return copy;
}
This does not crash, but it looks so suspiciously memory-leaking...
(the alloc/init is not paired with a release on my side). When trying
to follow the (few) suggestions the docs give me, I tried this (but it
did not work, the app crashed as soon as the TableView wanted to
redraw):
- (id)copyWithZone:(NSZone *)zone
{
PCShoppingCartCell *copy = [super copyWithZone:zone];
[ copy _initSubCells]; // This inits and sets up the NSPopUpButtonCell
return copy;
}
Can anybody give me advice on how I do this the right way?
Kind regards,
Michael -
On 6 Nov 2004, at 03:16, Michael Becker wrote:
> I have a subclass of NSCell (for a TableView) that is supposed to
> display an image and an NSPopUpButtonCell. Everything works fine so
> far, but I obviously need to override -copyWithZone:. Here's what I
> came up with:
>
> - (id)copyWithZone:(NSZone *)zone {
> PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
> initImageCell:nil];
> return copy;
> }
>
> This does not crash, but it looks so suspiciously memory-leaking...
> (the alloc/init is not paired with a release on my side).
As far as I'm aware, returning a copy with retain count 1 is the right
thing to do. As you probably know, you need to pair alloc/release, as
well as copy/release (in other general code). Therefore a copied object
must be returned with a retain count of 1, or it'd be over-released.
> When trying to follow the (few) suggestions the docs give me, I tried
> this (but it did not work, the app crashed as soon as the TableView
> wanted to redraw):
>
> - (id)copyWithZone:(NSZone *)zone
> {
> PCShoppingCartCell *copy = [super copyWithZone:zone];
> [ copy _initSubCells]; // This inits and sets up the NSPopUpButtonCell
> return copy;
> }
What you're doing there is calling copyWithZone: on the superclass,
NSCell. This returns an NSCell (which wouldn't implement your own
_initSubCells method), not a PCShoppingCartCell.
Jonathon Mah
<me...> -
At 17:46 Uhr +0100 05.11.2004, Michael Becker wrote:
> - (id)copyWithZone:(NSZone *)zone {
> PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
> initImageCell:nil];
> return copy;
> }
>
> This does not crash, but it looks so suspiciously memory-leaking...
> (the alloc/init is not paired with a release on my side). When
> trying to follow the (few) suggestions the docs give me, I tried
> this (but it did not work, the app crashed as soon as the TableView
> wanted to redraw):
That's just fine. It doesn't leak, because methods with "copy" in
their name, by definition, return retained objects. So, whoever calls
this method knows they're responsible for releasing the object they
get.
I'm not sure though whether you shouldn't be calling [super
copyWithZone: zone] instead of allocating a new object, and then just
copy over those instance variables your subclass adds to the ones of
the superclass.
--
Cheers,
M. Uli Kusterer
------------------------------------------------------------
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de -
Is there an Apple document that tells us how to do it exactly?
I know we must return an object identical to "self" ... but do we
invoke super copyWithZone? etc. etc.
On Fri, 5 Nov 2004 19:31:36 +0100, M. Uli Kusterer
<witness.of.teachtext...> wrote:
> At 17:46 Uhr +0100 05.11.2004, Michael Becker wrote:
>
>
>> - (id)copyWithZone:(NSZone *)zone {
>> PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
>> initImageCell:nil];
>> return copy;
>> }
>>
>> This does not crash, but it looks so suspiciously memory-leaking...
>> (the alloc/init is not paired with a release on my side). When
>> trying to follow the (few) suggestions the docs give me, I tried
>> this (but it did not work, the app crashed as soon as the TableView
>> wanted to redraw):
>
> That's just fine. It doesn't leak, because methods with "copy" in
> their name, by definition, return retained objects. So, whoever calls
> this method knows they're responsible for releasing the object they
> get.
>
> I'm not sure though whether you shouldn't be calling [super
> copyWithZone: zone] instead of allocating a new object, and then just
> copy over those instance variables your subclass adds to the ones of
> the superclass.
> --
> Cheers,
> M. Uli Kusterer
> ------------------------------------------------------------
> "The Witnesses of TeachText are everywhere..."
> http://www.zathras.de
>
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/<jolivierld...>
>
> This email sent to <jolivierld...>
>
--
--Olivier -
On Nov 5, 2004, at 1:52 PM, Jean-Olivier Lanctôt wrote:
> Is there an Apple document that tells us how to do it exactly?
I was just looking into this yesterday. Check out the NSCopying
protocol docs.
<http://developer.apple.com/documentation/Cocoa/Reference/Foundation/
ObjC_classic/Protocols/NSCopying.html>
DocoaBrowser also rocks for this:
<http://www.iwascoding.com/DocoaBrowser/>
> On Fri, 5 Nov 2004 19:31:36 +0100, M. Uli Kusterer
> <witness.of.teachtext...> wrote:
>> At 17:46 Uhr +0100 05.11.2004, Michael Becker wrote:
>>
>>
>>> - (id)copyWithZone:(NSZone *)zone {
>>> PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
>>> initImageCell:nil];
>>> return copy;
>>> }
I implemented by copyWithZone: method using allocWithZone:, just to
preserve the use of the zone argument. I don't know if zones are used
much any more, so maybe it's doesn't matter and a plain alloc: would
suffice.
- Bill -
On Nov 5, 2004, at 12:52 PM, Jean-Olivier Lanctôt wrote:
> Is there an Apple document that tells us how to do it exactly?If the superclass supports NSCopying, you should use [super
>
> I know we must return an object identical to "self" ... but do we
> invoke super copyWithZone? etc. etc.
>
copyWithZone:zone]. If it does not, you are implementing the
base-level copyWithZone; a super call is impossible. In that case, you
use alloc and init as normal, using your setters to set all the current
object's instance variables on the new one.
If the superclass supports copyWithZone and you therefore use [super
copyWithZone:zone], keep in mind that your instance variables will be
'lightly' (not sure the proper word) copied - they point to the same
memory addresses but are NOT retained. You therefore want to manually
set all of your subclass's instasnce variables, like so:
//Copy
- (id)copyWithZone:(NSZone *)zone
{
MyClass *newCell = [super copyWithZone:zone];
/* Font is a retained NSFont* */
[newCell setFont:font];
/* subString is a retained NSString* */
[newCell setSubString:subString];
return(newCell);
}
>
> On Fri, 5 Nov 2004 19:31:36 +0100, M. Uli Kusterer
> <witness.of.teachtext...> wrote:
>> At 17:46 Uhr +0100 05.11.2004, Michael Becker wrote:
>>
>>
>>> - (id)copyWithZone:(NSZone *)zone {
>>> PCShoppingCartCell *copy = [[ PCShoppingCartCell alloc]
>>> initImageCell:nil];
>>> return copy;
>>> }
>>>
>>> This does not crash, but it looks so suspiciously memory-leaking...
>>> (the alloc/init is not paired with a release on my side). When
>>> trying to follow the (few) suggestions the docs give me, I tried
>>> this (but it did not work, the app crashed as soon as the TableView
>>> wanted to redraw):
>>
>> That's just fine. It doesn't leak, because methods with "copy" in
>> their name, by definition, return retained objects. So, whoever calls
>> this method knows they're responsible for releasing the object they
>> get.
>>
>> I'm not sure though whether you shouldn't be calling [super
>> copyWithZone: zone] instead of allocating a new object, and then just
>> copy over those instance variables your subclass adds to the ones of
>> the superclass.
>> --
>> Cheers,
>> M. Uli Kusterer
>> ------------------------------------------------------------
>> "The Witnesses of TeachText are everywhere..."
>> http://www.zathras.de
>>
>>
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Cocoa-dev mailing list (<Cocoa-dev...>)
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/
>> <jolivierld...>
>>
>> This email sent to <jolivierld...>
>>
>
>
> --
> --Olivier
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/<evan.s...>
>
> This email sent to <evan.s...>
>
-
At 13:52 Uhr -0500 05.11.2004, Jean-Olivier Lanctôt wrote:
> Is there an Apple document that tells us how to do it exactly?
>
> I know we must return an object identical to "self" ... but do we
> invoke super copyWithZone? etc. etc.
Well, googling a little, the best docs are probably in:
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Tasks/
ImplementCopy.html
and then there's a little more in:
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_cl
assic/Classes/NSObject.html#copy
<<
(id)copy
Convenience method for classes that adopt the
NSCopying protocol. This method returns the
object returned by the NSCopying protocol method
copyWithZone: where the zone is nil. An exception
is raised if there is no implementation for
copyWithZone:.
NSObject does not itself support the NSCopying
protocol. Subclasses must support the protocol
and implement the copyWithZone: method. A
subclass version of the copyWithZone: method
should send the message to super first, to
incorporate its implementation, unless the
subclass descends directly from NSObject.
>>
More info in
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_cl
assic/Protocols/NSCopying.html#//apple_ref/doc/uid/20000053/BCIJFCDH
<<
- (id)copyWithZone:(NSZone *)zone
Returns a new instance that's a copy of the
receiver. Memory for the new instance is
allocated from zone, which may be nil. If zone is
nil, the new instance is allocated from the
default zone, which is returned from the function
NSDefaultMallocZone. The returned object is
implicitly retained by the sender, who is
responsible for releasing it. The copy returned
is immutable if the consideration "immutable vs.
mutable" applies to the receiving object;
otherwise the exact nature of the copy is
determined by the class.
>>--
Cheers,
M. Uli Kusterer
------------------------------------------------------------
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de -
At 15:50 Uhr -0600 05.11.2004, Evan Schoenberg wrote:
> If the superclass supports copyWithZone and you therefore use [super
> copyWithZone:zone], keep in mind that your instance variables will
> be 'lightly' (not sure the proper word) copied - they point to the
> same memory addresses but are NOT retained.
"Shallow copy" is what you're fishing for.
> You therefore want to manually set all of your subclass's instasnce
> variables, like so:
>
> //Copy
> - (id)copyWithZone:(NSZone *)zone
> {
> MyClass *newCell = [super copyWithZone:zone];
>
> /* Font is a retained NSFont* */
> [newCell setFont:font];
>
> /* subString is a retained NSString* */
> [newCell setSubString:subString];
> return(newCell);
> }
No! If your setFont: looks like the typical one:
-(void) setFont: (NSFont*)f
{
if( font != f )
{
[font release];
font = [f retain];
}
}
This will simply do nothing, and thus not retain the instance
variable. Or if you're using the other variant:
-(void) setFont: (NSFont*)f
{
[font autorelease];
font = [f retain];
}
This will release an object that was never retained by you, thus
effectively also failing to do the additional "retain" needed to give
your copy ownership of the NSFont. Apple recommends to do:
-(id) copyWithZone: (NSZone*)zone
{
MyClass *newCell = [super copyWithZone: zone];
newCell->font = nil;
[newCell setFont: font];
newCell->subString = nil;
[newCell setSubString: subString];
return newCell;
}
--
Cheers,
M. Uli Kusterer
------------------------------------------------------------
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de -
Well I just learned a new thing...
anyway, I have this very WEIRD crash in my app (which is, BTW, the
ONLY bug left until I can release 1.0) that I just can't squash.
*Maybe* it has to do with my wrong manner of overriding copyWithZone??
What do you guys think.. I have something like 5 custom classes
implementing it and I don't do it the right way... so could that be
the reason for weird crashes? I'm not on my work comp. right now so I
can't check.
On Fri, 5 Nov 2004 23:24:40 +0100, M. Uli Kusterer
<witness.of.teachtext...> wrote:
> At 15:50 Uhr -0600 05.11.2004, Evan Schoenberg wrote:
>> If the superclass supports copyWithZone and you therefore use [super
>> copyWithZone:zone], keep in mind that your instance variables will
>> be 'lightly' (not sure the proper word) copied - they point to the
>> same memory addresses but are NOT retained.
>
> "Shallow copy" is what you're fishing for.
>
>
>
>> You therefore want to manually set all of your subclass's instasnce
>> variables, like so:
>>
>> //Copy
>> - (id)copyWithZone:(NSZone *)zone
>> {
>> MyClass *newCell = [super copyWithZone:zone];
>>
>> /* Font is a retained NSFont* */
>> [newCell setFont:font];
>>
>> /* subString is a retained NSString* */
>> [newCell setSubString:subString];
>> return(newCell);
>> }
>
> No! If your setFont: looks like the typical one:
>
> -(void) setFont: (NSFont*)f
> {
> if( font != f )
> {
> [font release];
> font = [f retain];
> }
> }
>
> This will simply do nothing, and thus not retain the instance
> variable. Or if you're using the other variant:
>
> -(void) setFont: (NSFont*)f
> {
> [font autorelease];
> font = [f retain];
> }
>
> This will release an object that was never retained by you, thus
> effectively also failing to do the additional "retain" needed to give
> your copy ownership of the NSFont. Apple recommends to do:
>
> -(id) copyWithZone: (NSZone*)zone
> {
> MyClass *newCell = [super copyWithZone: zone];
>
> newCell->font = nil;
> [newCell setFont: font];
>
> newCell->subString = nil;
> [newCell setSubString: subString];
>
> return newCell;
> }
>
> --
>
>
> Cheers,
> M. Uli Kusterer
> ------------------------------------------------------------
> "The Witnesses of TeachText are everywhere..."
> http://www.zathras.de
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/<jolivierld...>
>
> This email sent to <jolivierld...>
>
--
--Olivier -
Why don't you check the crash log or run the application in the
debugger until it crashes. You'll get a stack trace from which will
help you pinpoint the problem.
- Byron
On Nov 5, 2004, at 3:27 PM, Jean-Olivier Lanctôt wrote:
> Well I just learned a new thing...
>
> anyway, I have this very WEIRD crash in my app (which is, BTW, the
> ONLY bug left until I can release 1.0) that I just can't squash.
> *Maybe* it has to do with my wrong manner of overriding copyWithZone??
> What do you guys think.. I have something like 5 custom classes
> implementing it and I don't do it the right way... so could that be
> the reason for weird crashes? I'm not on my work comp. right now so I
> can't check.
>
Byron Wright
Software Developer
Siemens Business Services Media
(formerly BBC Technology)
www.bbctechnology.com
www.siemens.co.uk/sbs
This e-mail (and any attachments) contains confidential information and
is for the exclusive use of the addressee/s. Any views contained in
this e-mail are not the views of Siemens Business Services Media
Holdings Ltd unless specifically stated. If you are not the addressee,
then any distribution, copying or use of this e-mail is prohibited. If
received in error, please advise the sender and delete/destroy it
immediately. We accept no liability for any loss or damage suffered by
any person arising from use of this e-mail/fax. Please note that
Siemens Business Services Media Holdings Ltd monitors e-mails sent or
received. Further communication will signify your consent to this.
Siemens Business Services Media Holdings Ltd
Registered No: 04128934 England
Registered Office: Siemens House, Oldbury, Bracknell, Berkshire, RG12
8FZ -
Yes well. I'm not a newbie (far from it, I'd say ;-). I already did
that... etc etc. The bug has been around since a LONG time and I
haven't been able to fix it!
It's crashing upon collapse of the LAST item in my outlineview...
here's the BT...
i'm about to just hire someone to do it for me.. I just can't see WHY
it does this.
Thread 0 Crashed:
0 com.apple.CoreFoundation 0x90190f9c CFRetain + 0x20
1 com.apple.CoreFoundation 0x9019cb2c CFDictionaryAddValue + 0x1f4
2 com.apple.CoreFoundation 0x901ae434 CFDictionaryCreate + 0x6c
3 com.apple.Foundation 0x909fbcdc -[NSPlaceholderDictionary
initWithObjects:forKeys:count:] + 0xf4
4 com.apple.Foundation 0x90a00fe0 +[NSDictionary
dictionaryWithObjectsAndKeys:] + 0x144
5 com.apple.AppKit 0x930b8388 -[NSOutlineView
_postItemDidCollapseNotification:] + 0x5c
6 com.apple.AppKit 0x930b6e48 -[NSOutlineView
_collapseItemEntry:collapseChildren:clearExpandState:recursionLevel:]
+ 0x208
7 com.apple.AppKit 0x930b6b74 -[NSOutlineView
_collapseItem:collapseChildren:clearExpandState:] + 0x158
8 com.apple.AppKit 0x930b93a0 -[NSOutlineView
collapseItem:collapseChildren:] + 0x7c
9 com.apple.AppKit 0x930b7e28 -[NSOutlineView
_doUserExpandOrCollapseOfItem:isExpand:optionKeyWasDown:] + 0x3a0
10 com.apple.AppKit 0x930b9aa0 -[NSOutlineView
mouseTracker:didStopTrackingWithEvent:] + 0x104
11 com.apple.AppKit 0x92f9db08 -[NSMouseTracker
stopTrackingWithEvent:] + 0xb8
12 com.apple.AppKit 0x92f9d1ac -[NSMouseTracker
trackWithEvent:inView:withDelegate:] + 0x164
13 com.apple.AppKit 0x92f38670 -[NSOutlineView mouseDown:] + 0x274
14 com.clichedev.burnoutmenu 0x00021b30 -[BMManagerOutlineView
mouseDown:] + 0x64 (BMManagerOutlineView.m:57)
15 com.apple.AppKit 0x92e024d4 -[NSWindow sendEvent:] + 0x10e4
16 com.apple.AppKit 0x92df4b98 -[NSApplication sendEvent:] + 0xebc
17 com.apple.AppKit 0x92dfcfb0 -[NSApplication run] + 0x240
18 com.apple.AppKit 0x92eb948c NSApplicationMain + 0x1d0
19 com.clichedev.burnoutmenu 0x00003234 main + 0x6c (main.m:23)
20 com.clichedev.burnoutmenu 0x00002cb8 _start + 0x188 (crt.c:267)
21 dyld 0x8fe1a558 _dyld_start + 0x64
On Fri, 5 Nov 2004 15:39:30 -0800, Byron Wright
<byron...> wrote:
> Why don't you check the crash log or run the application in the
> debugger until it crashes. You'll get a stack trace from which will
> help you pinpoint the problem.
>
> - Byron
>
>
>
> On Nov 5, 2004, at 3:27 PM, Jean-Olivier Lanctôt wrote:
>
>> Well I just learned a new thing...
>>
>> anyway, I have this very WEIRD crash in my app (which is, BTW, the
>> ONLY bug left until I can release 1.0) that I just can't squash.
>> *Maybe* it has to do with my wrong manner of overriding copyWithZone??
>> What do you guys think.. I have something like 5 custom classes
>> implementing it and I don't do it the right way... so could that be
>> the reason for weird crashes? I'm not on my work comp. right now so I
>> can't check.
>>
>
> Byron Wright
> Software Developer
> Siemens Business Services Media
> (formerly BBC Technology)
> www.bbctechnology.com
> www.siemens.co.uk/sbs
>
> This e-mail (and any attachments) contains confidential information and
> is for the exclusive use of the addressee/s. Any views contained in
> this e-mail are not the views of Siemens Business Services Media
> Holdings Ltd unless specifically stated. If you are not the addressee,
> then any distribution, copying or use of this e-mail is prohibited. If
> received in error, please advise the sender and delete/destroy it
> immediately. We accept no liability for any loss or damage suffered by
> any person arising from use of this e-mail/fax. Please note that
> Siemens Business Services Media Holdings Ltd monitors e-mails sent or
> received. Further communication will signify your consent to this.
>
> Siemens Business Services Media Holdings Ltd
> Registered No: 04128934 England
> Registered Office: Siemens House, Oldbury, Bracknell, Berkshire, RG12
> 8FZ
>
>
--
--Olivier -
I think one fine point has been missed until now (not sure what the
Apple docs have to say on it). If you derive from NSObject, you should
not call [[MyClass alloc] init] but [[[self class] alloc] init] to get
an instantiation of the right subclass. This might be causing your
problems...
Regards
Steven
--
<steven...>
http://sprintteam.nl/
Op 6-nov-04 om 0:27 heeft Jean-Olivier Lanctôt het volgende geschreven:
> Well I just learned a new thing...
>
> anyway, I have this very WEIRD crash in my app (which is, BTW, the
> ONLY bug left until I can release 1.0) that I just can't squash.
> *Maybe* it has to do with my wrong manner of overriding copyWithZone??
> What do you guys think.. I have something like 5 custom classes
> implementing it and I don't do it the right way... so could that be
> the reason for weird crashes? I'm not on my work comp. right now so I
> can't check.
>
-
At 15:39 Uhr -0800 05.11.2004, Byron Wright wrote:
> Why don't you check the crash log or run the application in the
> debugger until it crashes. You'll get a stack trace from which will
> help you pinpoint the problem.
Though with memory bugs, the time at which you see the crash might
not be the time at which the actual bug occurred. If you overwrite
some memory, and it's still within your app's allocated range of
addresses, you won't notice until you next attempt to use the
overwritten data.
Most "weird" crashes are memory-related.
--
Cheers,
M. Uli Kusterer
------------------------------------------------------------
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de -
Not to rain on the parade but NSCopying does explain that you should
implement this method with one of the three available ways.
1. Super implements it and you want a deep copy. So you call [super
allocWithZone:] and use the memory selectors to set the elements that
your subclass adds.
ie.
-(id) copyWithZone: (NSZone*)zone {
MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
need to cast up to your subclass
// then set your memory state using the memory selectors and copy
newCell->font = [font copy];
newCell->subString = [subString copy];
return newCell;
}
2. Your super does not implement it. So you manually call [[self
allocWithZone:] init] and use the set/get methods to set your state.
-(id) copyWithZone: (NSZone*)zone {
MyClass *newCell = [[self allocWithZone:zone] init]; // we know
how to do this thanks to NSObject
// then set your memory state using the set/get methods we made
// Depending on teh implementation of your class these will most
likely be shallow copies
// Unless your mutators copy incoming state and return copies of
internal state to
// provide another level of encapsulation
[newCell setFont:font];
[newCell setSubString:subString];
return newCell;
}
3. And last but not least, LIE. To be honest cells are supposed to be
lightweight and fast so why spend time copying immutable state
variables, instead we just point to the ones we already have?
-(id) copyWithZone: (NSZone*)zone {
MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
need to cast up to your subclass
// then set your memory state using the memory selectors and point to
what you already have
newCell->font = font;
newCell->subString = subString;
return newCell;
}
The last method is good since it's MUCH faster and NSCells are
instantiated then their -setObjectValue: is called so this gets
changed anyway. However, this also lets you know when something is
wrong since all your cells look the same and have the same info for
whatever reason that is probably -willDisplayCell related. Yea, i
make a lot of custom cells.
On Sat, 6 Nov 2004 16:50:01 +0100, M. Uli Kusterer
<witness.of.teachtext...> wrote:
> At 15:39 Uhr -0800 05.11.2004, Byron Wright wrote:
>> Why don't you check the crash log or run the application in the
>> debugger until it crashes. You'll get a stack trace from which will
>> help you pinpoint the problem.
>
> Though with memory bugs, the time at which you see the crash might
> not be the time at which the actual bug occurred. If you overwrite
> some memory, and it's still within your app's allocated range of
> addresses, you won't notice until you next attempt to use the
> overwritten data.
>
> Most "weird" crashes are memory-related.
> --
>
>
> Cheers,
> M. Uli Kusterer
> ------------------------------------------------------------
> "The Witnesses of TeachText are everywhere..."
> http://www.zathras.de
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/<karl.adam...>
>
> This email sent to <karl.adam...>
>
-
oops, sent in what would definetely crash your apps, the LIEing
technique retains the elements rather than just sets them because
otherwise when they do get set and it was released in one place, it
would crash for no longer being valid elsewhere.
The 3rd example should read:
-(id) copyWithZone: (NSZone*)zone {
MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
need to cast up to your subclass
// then set your memory state using the memory selectors and point to
what you already have
newCell->font = [font retain];
newCell->subString = [subString retain];
return newCell;
}
On Mon, 8 Nov 2004 20:04:13 -0500, The Karl Adam <karl.adam...> wrote:
> Not to rain on the parade but NSCopying does explain that you should
> implement this method with one of the three available ways.
>
> 1. Super implements it and you want a deep copy. So you call [super
> allocWithZone:] and use the memory selectors to set the elements that
> your subclass adds.
> ie.
> -(id) copyWithZone: (NSZone*)zone {
> MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
> need to cast up to your subclass
>
> // then set your memory state using the memory selectors and copy
> newCell->font = [font copy];
> newCell->subString = [subString copy];
>
> return newCell;
> }
>
> 2. Your super does not implement it. So you manually call [[self
> allocWithZone:] init] and use the set/get methods to set your state.
>
> -(id) copyWithZone: (NSZone*)zone {
> MyClass *newCell = [[self allocWithZone:zone] init]; // we know
> how to do this thanks to NSObject
>
> // then set your memory state using the set/get methods we made
> // Depending on teh implementation of your class these will most
> likely be shallow copies
> // Unless your mutators copy incoming state and return copies of
> internal state to
> // provide another level of encapsulation
> [newCell setFont:font];
> [newCell setSubString:subString];
>
> return newCell;
> }
>
> 3. And last but not least, LIE. To be honest cells are supposed to be
> lightweight and fast so why spend time copying immutable state
> variables, instead we just point to the ones we already have?
>
> -(id) copyWithZone: (NSZone*)zone {
> MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
> need to cast up to your subclass
>
> // then set your memory state using the memory selectors and point to
> what you already have
> newCell->font = font;
> newCell->subString = subString;
>
> return newCell;
> }
>
> The last method is good since it's MUCH faster and NSCells are
> instantiated then their -setObjectValue: is called so this gets
> changed anyway. However, this also lets you know when something is
> wrong since all your cells look the same and have the same info for
> whatever reason that is probably -willDisplayCell related. Yea, i
> make a lot of custom cells.
>
> On Sat, 6 Nov 2004 16:50:01 +0100, M. Uli Kusterer
>
>
> <witness.of.teachtext...> wrote:
>> At 15:39 Uhr -0800 05.11.2004, Byron Wright wrote:
>>> Why don't you check the crash log or run the application in the
>>> debugger until it crashes. You'll get a stack trace from which will
>>> help you pinpoint the problem.
>>
>> Though with memory bugs, the time at which you see the crash might
>> not be the time at which the actual bug occurred. If you overwrite
>> some memory, and it's still within your app's allocated range of
>> addresses, you won't notice until you next attempt to use the
>> overwritten data.
>>
>> Most "weird" crashes are memory-related.
>> --
>>
>>
>> Cheers,
>> M. Uli Kusterer
>> ------------------------------------------------------------
>> "The Witnesses of TeachText are everywhere..."
>> http://www.zathras.de
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Cocoa-dev mailing list (<Cocoa-dev...>)
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/<karl.adam...>
>>
>> This email sent to <karl.adam...>
>>
>
-
At 20:04 Uhr -0500 08.11.2004, The Karl Adam wrote:
> -(id) copyWithZone: (NSZone*)zone {
> MyClass *newCell = [[self allocWithZone:zone] init]; // we know
> how to do this thanks to NSObject
Here's a typo: This should be [self class]. allocWithZone: is a
class method, not an instance method.
> -(id) copyWithZone: (NSZone*)zone {
> MyClass *newCell = (MyClass *)[super copyWithZone:zone]; // you
> need to cast up to your subclass
>
> // then set your memory state using the memory selectors and point to
> what you already have
> newCell->font = font;
> newCell->subString = subString;
>
> return newCell;
> }
This is buggy as well. You can't just assign font and subString when
they are objects, because usually your class will need to retain
them. So this should be:
newCell->font = [font retain];
newCell->subString = [subString retain];
or, if you follow the recommendation from many pros that you should
*always* use accessors to manipulate your variables, you should do
what Apple does in its sample code:
newCell->font = nil;
[newCell setFont: font];
newCell->subString = nil;
[newCell setSubString: subString];
Again, remember that the nil assignment is necessary if the super
calls NSCopyObject(), which performs a shallow copy, meaning there
are un-retained pointers in those variables. However, you can only do
this if you know that super calls NSCopyObject, because if it just
calls allocWithZone and init, then these pointers have already been
retained, and you actually need to use the accessor to ensure the old
value is released and the new one retained.
Don't ask me why it's so complicated. I guess NSCopyObject() was
created for classes that mostly contain data and few pointers to
objects.
--
Cheers,
M. Uli Kusterer
------------------------------------------------------------
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de



