Re: [SOLVED] NSString's drawInRect: problems
Re: [SOLVED] NSString's drawInRect: problems
- Subject: Re: [SOLVED] NSString's drawInRect: problems
- From: Dragan Milić <email@hidden>
- Date: Thu, 2 Jun 2005 04:08:30 +0200
Hi,
problem solved, many thanks to Jonathan who has introduced me with zombies, it was much easier to track things down using them, I guess I was too lazy to take a look into detailed crash report. Anyway, here are some insights, maybe it will help someone else.
Yes, count: message has been sent to released object, but it was not an instance of NSArray, or any other object I've created, actually it was an instance of NSAttributeDictionary, and since It's private to the framework, I have no responsibility of allocate/retain/release it, but it clearly pointed out to me that the problem has been caused by attributes I'm using in drawing strings in preview cell. An instance of NSDictionary class holding those attributes was created locally inside overridden drawWithFrame:inView method, autoreleased of course. The first thing that came up to my mind was to promote those attributes to instance variable of the NSBrowserCell subclass, and it worked with many windows opened. The only modification I've made after this "discovery" was to create that NSDictionary instance variable (actually, two of them) only if the cell is set as a preview cell, inside it's setPreviewCell accessor method with YES passed as argument, since I don't want memory and time wasted for all the other cells, which don't need those attributes and are much more frequent.
The only thing I wonder about is the fact that I've been using string attributes created locally inside drawWithFrame:inView and autoreleased in NSCell (mostly NSTextFieldCell ) subclasses many times before, for example to change NSLineBreakMode, to add hyperlinks to cells, etc. and I've never experienced any problem with that approach. I guess it's because NSBrowserCell is a little different beast. I did it with NSBrowserCell subclasses too, but always ended sending drawWithFrame:inView to super, but now that's not the case if the cell is preview cell. That might be the reason.
Milke
On 31.
мај 2005., at 21:53, Jonathan Hess wrote:
Sounds like a classic over-release problem. Have you looked into using zombies? If you aren't familiar with zombies, I'll give a quick run down as to how they work. When an object is released down to zero it is typically deallocated. After this point a new object is put in its place - you've seen NSCFData take the over released objects place in most instances. With zombies, objects never go away, and instead they raise when you try to send them a message after their retain count has fallen to zero.
You can find some more info here - http://developer.apple.com/technotes/tn2004/tn2124.html
Alternatively, in your ~/.gdbinit file you can add
set env MallocHelp=NO
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie class]
fb szone_error
To debug with zombies. Now, as soon as you over release the bad object, then message it again, you'll break on one of the zombie methods.
Jon Hess
On May 31, 2005, at 12:00 PM, Dragan Milić wrote:
Hi all.
I have a problem and I'm out of ideas how to solve it. I've made a NSBrowser subclass which, among other things (full drag'n'drop support etc...), shows Finder-like preview column in the last column, if a leaf cell is selected. I made browser display another column to the right if a leaf cell is selected by combining following: delegate method -browser:numberOfRowsInColumn: returns "1" if a leaf cell is selected, so it will create a cell for that additional column. But, since the cell is not leaf, browser still won't add and display additional column, so I track for it's path change, and when it's changed (new single cell selected) I ask if that cell is leaf and if it is, I programatically add new column to the right by sending addColumn: and specify different cell height for that column (preview cell should be of height same as its enclosing matrix superview) by obtaining its matrix with -matrixOfColumn: and sending to it -setCellSize: And, it works.
Now, the cell. I subclassed NSBrowserCell, adding to it instance field BOOL isPeviewCell. In it's -drawInteriorWithFrame:inView: I check whether it's preview cell (that value is set outside, namely in delegate method browser:willDisplayCell:atRow:column:), and if it isn't, I simply forward method call to super. If it is preview cell, I make some custom drawing inside cell frame. In doing so, I dissolve cell's image of appropriate size to appropriate position, and draw some strings, showing item's (represented by selected cell) info. This also works beautifully. But only if I have only one window open! And, to my sadness, I need multidocument app, with many windows open. Maybe I should mention that everything is working if none of preview columns has ever been made visible and preview cell drawn. But, as soon as it happens, the problems start coming. The app just crashes, sometimes with SIGSEGV, sometimes with SIGBUS, sometimes I get console response such as:
*** -[NSCFData count]: selector not recognized
but instead of NSCFData sometimes it's NSCFType, or NSIDEnumerator... but the selector is always the same, count: Now, I have menu count: messages sent in my code, but in those situations somehow wrong object sneaks in and get that message sent. The app usually crashes when opening new window while there is already opened one (with column view showed at least once), or if it survives opening two windows it would most probably crash when closing some of them. I should say that my custom browserCell has two instance variables of NSArray class (keeping drawn info strings), but I made their proper handling overriding cell's -copyWithZone: method.
Very long intro, isn't it. Trying to find the origin of the problem, I've come to the point when I removed ONLY NSString's drawInRect:withAttributes: methods invoked while preview cell is drawn (two of them). And the problem's gone! I know that it should be invoked only if a view has focus, but NSCell's -drawInteriorWithFrame:inView: is passed view that currently has focus, so that shouldn't be the reason for crashing. Nevertheless, I made sure to send drawRect:withAttributes: only if enclosing view has focus, even lock focus on it, but it didn't help.
Any help would be highly welcomed. If someone needs insight in my code to come up with some solution, please let me know.
Regards,
Milke
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden