Article View: comp.sys.next.programmer
Article #401Tips for using NXZones w/.nibs.
From: Scott Hess
Date: Sat, 01 Aug 1992 22:20
Date: Sat, 01 Aug 1992 22:20
128 lines
6240 bytes
6240 bytes
I use NXZone allocation heavily in my programs, and I've run across
a number of gotchas (as have a bunch of other people). The main
points I try to watch out for:
o First off, here's what my -free method looks like in these cases:
- free
{
NXZone *z=[self zone];
[super free];
if( z!=NXDefaultMallocZone()) {
NXDestroyZone( z);
}
return nil;
}
First off, note the check for the default malloc zone. You do
_not_ want to destroy it. Also, you may wish to put in other
checks, just in case there are other instances where the NXZone
shouldn't go away.
o The most important hint of all. Don't assume that you can just
destroy the NXZone and get away without called -free for your
objects unless you really know what you are doing. Perhaps
75% of all problems with NXZones come about when people do
things that they don't know how to do, just because they sound
neat. An airplane is neat, but you shouldn't fly it until
you've been trained.
Consider the alleged time you'll save. There are a surprising
number of objects in your average .nib, but there really aren't
_that_ many. Let's be liberal and call it 200. It's going to
take a _very_ small amount of time to -free each object
individually. So do it. Then destroy the NXZone, after you
_know_ that there's nothing surviving within it.
Besides, most of those objects are Views in your window(s),
which means you'll have to -free them _anyhow_. And you _should_
call -free on any other NeXTSTEP objects, just in case. The
number of non-NeXTSTEP objects in most of my .nib files is only
one - the File's Owner. Not much win in not freeing that!
o All Windows have a reference on the application-wide windowList.
If you don't call -free for Windows, this list is not updated
and your application will crash in short order.
o Watch out for PopUpLists. They aren't free by Window's when
the content Views are freed. You'll have to free them by going
through their cover button (you can connect to the cover button
using IB):
[coverButton setTarget:[[coverButton target] free]]
works well. Note my paranoia - I don't know whether or not
the coverButton will attempt to call its target after I free
it. But, I don't know that it _won't_, and thus I plan ahead
and assume that it might. If I'm wrong, I lose a couple bytes
and a couple milliseconds. If I didn't do this and was wrong,
my program will core dump. Don't make assumptions about source
code you don't have, unless someone explicitely tells you how
it works.
o Put all of your NXImages as .tiff or .eps files in the Project
inspector, _not_ as part of the .nib. Then, you don't have to
worry about them being allocated from your .nib's NXZone, and thus
in the future when you free the NXZone, you should be fine. You
can still access them easily using +findImageNamed:, or name
them in Buttons, just as always.
Also, you get the further advantage of being able to easily
edit the images without having to fight InterfaceBuilder to
replace edited versions. This also works with .snd files.
o Windows can free themselves, and all of their subviews. The
best idea is to set the Window to be freeOnClose from the IB
inspector. From your -windowWillClose: method in the delegate,
do something like:
- windowWillClose:sender
{
/* Make sure the Window doesn't talk to us anymore.
[sender setDelegate:nil];
/* We should lose our local reference to the window. */
myWindow=nil;
/* Don't free ourselves until later. */
return [NXApp delayedFree:self];
}
myWindow is the delegate's instance variable which points to
the Window. This is also only really useful when your delegate
is File's Owner and acts as the "controller" for the .nib (as
is the standard way people do it, see the many examples out
there on archives and in /NextDeveloper/Examples). Also, you
obviously shouldn't set freeOnClose if the window should hang
around (like, for instance, a Find Panel).
o If you can't rely on a Window to free itself, you have to watch
out. When you say [myWindow free], myWindow is _not_ freed at
that time. It's apparently scheduled for a delayedFree as I
do above for my delegate instance. Say myZone is the NXZone
that myWindow is stored in. If you do:
[myWindow free];
NXDestroyZone( myZone);
You are guaranteed to crash your program when it next reaches
the event loop. This caused me no end of problems in Stuart
(this is the direct cause of Stuart2.3 crashing when you run
out of ptys). My solution is to schedule a normal close-scenario
by doing:
[myWindow perform:@selector( performClose:) with:nil
afterDelay:1 cancelPrevious:NO];
Then, let your regular Window-closing machinery do the work.
Your first thought might be to call -performClose: directly.
If you've structured things like I do, that won't work. First,
in -performClose:, the Window is going to call -windowWillClose:,
so your delegate will schedule a -delayedFree:. Then, the
Window will schedule itself to be freed via -delayedFree:.
Thus, when you get back to the event loop, your -free will be
called before the Window's, which will crash things again.
Later,
--
scott hess <shess@ssesco.com> <Who's now in a programming Berserker-frenzy>
12901 Upton Avenue South, #326 Burnsville, MN 55337 (612) 895-1208 Anytime!
<I want to become so famous that people buy tapes of me reading source code>
Technical Details
Message-ID:
<SCOTT.92Aug1222013@nic.gac.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!usc!sol.ctr.columbia.edu!The-Star.honeywell.com!umn.edu!noc.msc.net!gacvx2.gac.edu!gacvax2!scottShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!usc!sol.ctr.columbia.edu!The-Star.honeywell.com!umn.edu!noc.msc.net!gacvx2.gac.edu!gacvax2!scott Newsgroups: comp.sys.next.programmer Subject: Tips for using NXZones w/.nibs. Message-ID: <SCOTT.92Aug1222013@nic.gac.edu> From: scott@nic.gac.edu (Scott Hess) Date: 1 Aug 92 22:20:13 Distribution: world Organization: Gustavus Adolphus College Nntp-Posting-Host: nic.gac.edu Lines: 128