Interface Builder & Wiring Objects
-
Good afternoon!
I am trying to learn Cocoa and am having difficulty remembering which
direction to CTRL-drag controls to wire up the controls in Interface
Builder. For example, dragging from my button to my App Controller
(NSObject) or vice versa. Does anyone have a way to explain this that
might make it stick?
It seems to me that a button should make a call to my App Controller
when the click event is fired; therefore I should CTRL-drag FROM the
button TO the NSObject. This would allow me to select the appropriate
Received Action (ie, "doSomething", etc."). However, if I need to do
something with a text box (read from it) and a table view (insert an
item), I should go the other way... since I'm going to fetch from the
text field and then insert into the NSArray that is feeding the text
view.
Sorry for such a noob question. Thank you, in advance, for your
patience and assistance.
-- Greg -
With new versions of IB, it's not even necessary to remember. Simply
right-click on an object and it will bring up a HUD with the list of
outlets or sent messages or whatever you need. Alternatively, you can
view this list in the outlets tab of the inspector window.
Even if the outlet you need is in a different object than the one
you've selected, you can just drag from the "new referencing outlet"
option to the object with that outlet. Using this right-click
technique, selection is possible in either direction.
Luke
On Nov 17, 2008, at 10:09 AM, Greg Deward wrote:
> Good afternoon!
>
> I am trying to learn Cocoa and am having difficulty remembering
> which direction to CTRL-drag controls to wire up the controls in
> Interface Builder. For example, dragging from my button to my App
> Controller (NSObject) or vice versa. Does anyone have a way to
> explain this that might make it stick?
>
> It seems to me that a button should make a call to my App Controller
> when the click event is fired; therefore I should CTRL-drag FROM the
> button TO the NSObject. This would allow me to select the
> appropriate Received Action (ie, "doSomething", etc."). However, if
> I need to do something with a text box (read from it) and a table
> view (insert an item), I should go the other way... since I'm going
> to fetch from the text field and then insert into the NSArray that
> is feeding the text view.
>
> Sorry for such a noob question. Thank you, in advance, for your
> patience and assistance.
>
> -- Greg
-
On Nov 17, 2008, at 11:09 AM, Greg Deward wrote:
> Good afternoon!
>
> I am trying to learn Cocoa and am having difficulty remembering
> which direction to CTRL-drag controls to wire up the controls in
> Interface Builder. For example, dragging from my button to my App
> Controller (NSObject) or vice versa. Does anyone have a way to
> explain this that might make it stick?
Aaron Hillegass, in his "Cocoa Programming for Mac OS X" book explains
it this way:
"Now you are going to introduce some objects to each other....To
introduce one object to another, you will control-drag from the object
that needs to know to the object it needs to know about."
So, for instance, a class needs to know about its NSButton outlet, so
you control-drag from the class to the NSButton in the window (to set
the IBOutlet). The NSButton needs to know what method to call when it
is pressed, so you control-drag from the button to the class (to set
the IBAction).
Or do what Luke said in his response... :)
> It seems to me that a button should make a call to my App Controller
> when the click event is fired; therefore I should CTRL-drag FROM the
> button TO the NSObject. This would allow me to select the
> appropriate Received Action (ie, "doSomething", etc.").
Yep, sounds like you have the basic gist of it...
> However, if I need to do something with a text box (read from it)
> and a table view (insert an item), I should go the other way...
> since I'm going to fetch from the text field and then insert into
> the NSArray that is feeding the text view.
But, what triggers the action of reading from the text field and
inserting that into the array that feeds the table (you said text, but
I assume that's a typo) view? A button gets pressed? The user presses
Enter? You set the action of the object that does that action just as
you would otherwise. -
As you pointed out, you have two kinds of relationship in IB: outlets and actions.
> From a single object, you designate either an outlet object or a target object.For the target case, you have to specify the associated action selector.
Usually though, you don't draw both kinds of connection from the same kind of objects.
Controls send actions to target objects such as the First Responder.
Controllers use outlets to reference other UI objects in source code.
So you always CTRL-drag connections from your source object.
With the introduction of Cocoa Bindings, you now have a third kind of relationship in IB: bindings.
You don't have to CTRL-drag anything when using bindings since the connections are based on key path.
However, you can mix both use of connections, such as connecting the File Owner of your nib to the content object outlet of an ObjectController instance.
EG
-----Original Message-----
I am trying to learn Cocoa and am having difficulty remembering which
direction to CTRL-drag controls to wire up the controls in Interface
Builder. For example, dragging from my button to my App Controller
(NSObject) or vice versa. Does anyone have a way to explain this that
might make it stick?
It seems to me that a button should make a call to my App Controller
when the click event is fired; therefore I should CTRL-drag FROM the
button TO the NSObject. This would allow me to select the appropriate
Received Action (ie, "doSomething", etc."). However, if I need to do
something with a text box (read from it) and a table view (insert an
item), I should go the other way... since I'm going to fetch from the
text field and then insert into the NSArray that is feeding the text
view.
Sorry for such a noob question. Thank you, in advance, for your
patience and assistance.
-- Greg
------------------------------------------------------------
This message and any attachments (the "message") are confidential and intended solely for the addressee(s). Any unauthorised use or dissemination is prohibited. E-mails are susceptible to alteration. Neither DxO Labs nor any of its subsidiaries or affiliates shall be liable for the message if altered, changed or falsified.
Ce message et toutes les pieces jointes (ci-apres le "message") sont confidentiels et etablis a l'intention exclusive de ses destinataires. Toute utilisation ou diffusion non autorisee est interdite. Tout message electronique est susceptible d'alteration. DxO Labs et ses filiales declinent toute responsabilite au titre de ce message s'il a ete altere, modifie ou falsifie. -
Luke / Randall,
Thanks for replying. I did not want to embarrass Mr. Hillegass with
my ignorance, but his book IS the one I am trying to follow. I am
currently working on his "To Do List" example in Chapter 6 (page 110).
In my example, I have the following items in my App Controller class:
Text Field (along with an IBOutlet)
Button (along with an IBOutlet)
Table View (along with an IBOutlet)
Mutable Array instance variable
My concern is whether or not the DIRECTION in which I CTRL-drag the
objects. For example, if do I drag from the Button object to the App
Controller or do I CTRL-drag from the App Controller to the Button?
I'm coming from a C# / .NET environment. While there ARE visual
design tools involved, it is much more manual. For example, adding a
Button to a Form creates the implmentation in the source file. Double-
clicking the control then creates the event handler for the object.
Anything that you may want to do is handled programatically.
Basically, since I cannot see what is happening under the hood, I'm
beginning to second-guess that the calls will be made in the right
direction.
I hope that made sense. Again, my apologies for such a noob-ish
question.
Thanx,
Fred
On Nov 17, 2008, at 1:56 PM, Randall Meadows wrote:
> On Nov 17, 2008, at 11:09 AM, Greg Deward wrote:
>
>> Good afternoon!
>>
>> I am trying to learn Cocoa and am having difficulty remembering
>> which direction to CTRL-drag controls to wire up the controls in
>> Interface Builder. For example, dragging from my button to my App
>> Controller (NSObject) or vice versa. Does anyone have a way to
>> explain this that might make it stick?
>
> Aaron Hillegass, in his "Cocoa Programming for Mac OS X" book
> explains it this way:
>
> "Now you are going to introduce some objects to each other....To
> introduce one object to another, you will control-drag from the
> object that needs to know to the object it needs to know about."
>
> So, for instance, a class needs to know about its NSButton outlet,
> so you control-drag from the class to the NSButton in the window (to
> set the IBOutlet). The NSButton needs to know what method to call
> when it is pressed, so you control-drag from the button to the class
> (to set the IBAction).
>
> Or do what Luke said in his response... :)
>
>> It seems to me that a button should make a call to my App
>> Controller when the click event is fired; therefore I should CTRL-
>> drag FROM the button TO the NSObject. This would allow me to select
>> the appropriate Received Action (ie, "doSomething", etc.").
>
> Yep, sounds like you have the basic gist of it...
>
>> However, if I need to do something with a text box (read from it)
>> and a table view (insert an item), I should go the other way...
>> since I'm going to fetch from the text field and then insert into
>> the NSArray that is feeding the text view.
>
> But, what triggers the action of reading from the text field and
> inserting that into the array that feeds the table (you said text,
> but I assume that's a typo) view? A button gets pressed? The user
> presses Enter? You set the action of the object that does that
> action just as you would otherwise.
-
On Mon, Nov 17, 2008 at 11:36 AM, Greg Deward <greg.deward...> wrote:
> Luke / Randall,
>
> Thanks for replying. I did not want to embarrass Mr. Hillegass with my
> ignorance, but his book IS the one I am trying to follow. I am currently
> working on his "To Do List" example in Chapter 6 (page 110).
>
> In my example, I have the following items in my App Controller class:
>
> Text Field (along with an IBOutlet)
> Button (along with an IBOutlet)
> Table View (along with an IBOutlet)
> Mutable Array instance variable
>
> My concern is whether or not the DIRECTION in which I CTRL-drag the objects.
> For example, if do I drag from the Button object to the App Controller or
> do I CTRL-drag from the App Controller to the Button?
Think of it this way: The object that you drag FROM is the object
whose attributes you are changing.
So, dragging from a button to its target is roughly equivalent to calling:
[button setTarget: theTargetObject]
and dragging from, for instance, a view controller to its view is
equivalent to calling:
[viewController setView: theView]
--
Clark S. Cox III
<clarkcox3...> -
On Nov 17, 2008, at 2:36 PM, Greg Deward wrote:
> In my example, I have the following items in my App Controller class:
>
> Text Field (along with an IBOutlet)
> Button (along with an IBOutlet)
> Table View (along with an IBOutlet)
> Mutable Array instance variable
The technical term for these items is "instance variable," or "ivar"
for short. Your AppController class has instance variables of type
NSTextField, NSButton, etc. which are named myTextField, myButton, or
whatever made sense to you.
You don't have ivars "along with" outlets. An outlet *is* a
particular kind of ivar. It's an object reference that is declared in
such a way that IB recognizes it and allows you to assign its value
graphically in IB. Typically the declaration has the modifier
"IBOutlet" in front of it, as in:
@interface AppController : NSObject {
IBOutlet NSTextField *myTextField;
...
}
This is just a hint to IB to say "I want you to treat this ivar as an
outlet." The IBOutlet modifier has no other effect or purpose --
indeed, it's just a macro that evaluates to nothing.
> My concern is whether or not the DIRECTION in which I CTRL-drag the
> objects. For example, if do I drag from the Button object to the
> App Controller or do I CTRL-drag from the App Controller to the
> Button?
Remember that an outlet is an object reference. You can think of an
object reference as a pointer that points TO another object. When you
Control-drag, imagine an arrowhead at the end of the line you're
dragging. You're making a connection FROM where you started the drag
TO wherever you decide to drop that arrowhead. As was explained
earlier, you're making the FROM object aware of the TO object.
In your specific example, you would drag FROM your AppController
instance to each of the objects it needs to be aware of:
"Hey app controller, I want >>this to be the text field your
myTextField outlet points to."
"Hey app controller, I want >>this to be the button your myButton
outlet points to."
Then when the nib is loaded at runtime, the app controller's ivars
will point to those respective objects.
To specify a button's target/action, you would say "Hey button
[dragging from the button], I want >>this [dragging TO the app
controller] to be your target."
Similarly:
"Hey text field, I want >>this to be your delegate."
"Hey table view, I want >>this to be your data source." (And again if
you also want to set the table view's delegate.)
--Andy -
On Nov 17, 2008, at 1:46 PM, Andy Lee wrote:
> You don't have ivars "along with" outlets. An outlet *is* aGoing forward, you're encouraged to declare outlets as follows:
> particular kind of ivar. It's an object reference that is declared
> in such a way that IB recognizes it and allows you to assign its
> value graphically in IB. Typically the declaration has the modifier
> "IBOutlet" in front of it, as in:
> @interface AppController : NSObject {
> IBOutlet NSTextField *myTextField;
> ...
> }
>
@interface AppController : NSObject {
NSTextField *myTextField;
...
}
@property (nonatomic, retain) IBOutlet NSTextField *myTextField;
<http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articl
es/chapter_5_section_3.html>
mmalc -
On Nov 17, 2008, at 3:06 PM, mmalcolm crawford wrote:
> Going forward, you're encouraged to declare outlets as follows:Jeff asked (posted with permission):
> @interface AppController : NSObject {
> NSTextField *myTextField;
> ...
> }
> @property (nonatomic, retain) IBOutlet NSTextField *myTextField;
>
"One remaining question. Are you expected to release the outlet when
your
controller is dealloc'd? And did you have to prior to "properties"?
I believed the answer to the latter was "no" but I'm prepared to be
wrong on that.."
Since the property is declared with the 'retain' attribute, the memory
management semantics are made clear here. Yes, you should release the
outlet in dealloc.
The problem heretofor was that the story was a mess -- whether or not
you released the outlet was dependent upon what class File's Owner
inherited from, and whether or not you had accessor methods. The
principal advantage with the property-based pattern is that memory
management is consistent across all classes across all patterns. It
will also work on modern runtimes that use instance variable synthesis
(where there may be no instance variable declaration with which to
attach the IBOutlet).
There may be some variation; if you have a delegate that may be
connected using a delgate, then you may have:
@interface AppController : NSObject {
id delegate;
...
}
@property (nonatomic, assign) IBOutlet id delegate;
although again use of a property declaration makes the memory
management semantics clear (in this case you would of course not
release delegate in dealloc).
One other consideration, particularly in iPhone applications, is where
you might have outlets to subviews of a main view that might be
released in sime situations -- e.g. a UIViewController whose view is
released in didReceiveMemoryWarning. To ensure that you don't prolong
the lifetime of objects you got from the nib, you should set (use your
accessor methods to) set those variables to nil in the relevant
method, e.g.:
@interface MyController : UIViewController {
UILabel *label;
...
}
@property (nonatomic, retain) IBOutlet UILabel *label;
then
- (void)didReceiveMemoryWarning {
self.label = nil;
[super didReceiveMemoryWarning];
}
mmalc -
On Nov 17, 2008, at 9:11 PM, mmalcolm crawford wrote:
> One other consideration, particularly in iPhone applications, is
> where you might have outlets to subviews of a main view that might
> be released in sime situations -- e.g. a UIViewController whose view
> is released in didReceiveMemoryWarning. To ensure that you don't
> prolong the lifetime of objects you got from the nib, you should set
> (use your accessor methods to) set those variables to nil in the
> relevant method, e.g.:
>
> @interface MyController : UIViewController {
> UILabel *label;
> ...
> }
> @property (nonatomic, retain) IBOutlet UILabel *label;
>
> then
>
> - (void)didReceiveMemoryWarning {
> self.label = nil;
> [super didReceiveMemoryWarning];
> }
OK, this issue has come up for me very recently. It appears that on
iPhoneOS IBOutlets are retained, regardless of the presence of
properties. Even worse, in the presence of an assign property the
outlet is still retained. Whatever code is retaining the outlets
never releases them. So it seems that client code must release all
outlets.
The documentation on this is vague, with a lot of 'should's and not
clear statements of what really happens. Actually this isn't (only)
related to didReceiveMemoryWarning (which I hadn't considered related
to this problem until you raised it).
Is this the way that things are supposed to work on iPhone OS?
--
Brian Stern
<brians99...> -
On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
> OK, this issue has come up for me very recently. It appears that on
> iPhoneOS IBOutlets are retained, regardless of the presence of
> properties. Even worse, in the presence of an assign property the
> outlet is still retained. Whatever code is retaining the outlets
> never releases them. So it seems that client code must release all
> outlets.
Seems to me that the outlets must have a retain count of at least one
when they're unarchived, as though they were alloc'd. It makes sense
that the programmer should have to manually release objects in
dealloc. How else would it happen?
Luke -
On Nov 17, 2008, at 10:17 PM, Luke the Hiesterman wrote:
>
> On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
>
>> OK, this issue has come up for me very recently. It appears that
>> on iPhoneOS IBOutlets are retained, regardless of the presence of
>> properties. Even worse, in the presence of an assign property the
>> outlet is still retained. Whatever code is retaining the outlets
>> never releases them. So it seems that client code must release all
>> outlets.
>
> Seems to me that the outlets must have a retain count of at least
> one when they're unarchived, as though they were alloc'd. It makes
> sense that the programmer should have to manually release objects in
> dealloc. How else would it happen?
IBOutlets are not necessarily top level objects. Most are simply
views that happen to be in the view hierarchy. There will typically
be one top level object in an iPhone nib. This will be the view that
belongs to UIViewController. It is the UIViewController base class
that loads the nib. As long as it retains that top level view then
all the subviews will also be retained. They should be released when
the UIViewController releases its view outlet.
Furthermore, NSBundle loadNibNamed:owner:options: on iPhone OS returns
an array of the top level objects. It would be trivial for the
UIViewController base class object that is loading the nib to retain
that array and of course release it in its dealloc.
If user code doesn't retain the outlets I don't understand why user
code should be releasing those objects.
--
Brian Stern
<brians99...> -
On Nov 17, 2008, at 7:46 PM, Brian Stern wrote:
>
> On Nov 17, 2008, at 10:17 PM, Luke the Hiesterman wrote:
>
>>
>> On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
>>
>>> OK, this issue has come up for me very recently. It appears that
>>> on iPhoneOS IBOutlets are retained, regardless of the presence of
>>> properties. Even worse, in the presence of an assign property the
>>> outlet is still retained. Whatever code is retaining the outlets
>>> never releases them. So it seems that client code must release
>>> all outlets.
>>
>> Seems to me that the outlets must have a retain count of at least
>> one when they're unarchived, as though they were alloc'd. It makes
>> sense that the programmer should have to manually release objects
>> in dealloc. How else would it happen?
>
> IBOutlets are not necessarily top level objects. Most are simply
> views that happen to be in the view hierarchy. There will typically
> be one top level object in an iPhone nib. This will be the view
> that belongs to UIViewController. It is the UIViewController base
> class that loads the nib. As long as it retains that top level view
> then all the subviews will also be retained. They should be
> released when the UIViewController releases its view outlet.
Right, and view is a property of UIViewController. When you have your
UIViewController release view, that is an example of the programmer
releasing an outlet assigned from IB, which you seem to be arguing
that the programmer shouldn't have to release objects given to it from
IB.
Luke
>
>
> Furthermore, NSBundle loadNibNamed:owner:options: on iPhone OS
> returns an array of the top level objects. It would be trivial for
> the UIViewController base class object that is loading the nib to
> retain that array and of course release it in its dealloc.
>
> If user code doesn't retain the outlets I don't understand why user
> code should be releasing those objects.
>
>
> --
> Brian Stern
> <brians99...>
-
On Nov 17, 2008, at 10:53 PM, Luke the Hiesterman wrote:
>
> On Nov 17, 2008, at 7:46 PM, Brian Stern wrote:
>
>>
>> On Nov 17, 2008, at 10:17 PM, Luke the Hiesterman wrote:
>>
>>>
>>> On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
>>>
>>>> OK, this issue has come up for me very recently. It appears that
>>>> on iPhoneOS IBOutlets are retained, regardless of the presence of
>>>> properties. Even worse, in the presence of an assign property
>>>> the outlet is still retained. Whatever code is retaining the
>>>> outlets never releases them. So it seems that client code must
>>>> release all outlets.
>>>
>>> Seems to me that the outlets must have a retain count of at least
>>> one when they're unarchived, as though they were alloc'd. It makes
>>> sense that the programmer should have to manually release objects
>>> in dealloc. How else would it happen?
>>
>> IBOutlets are not necessarily top level objects. Most are simply
>> views that happen to be in the view hierarchy. There will
>> typically be one top level object in an iPhone nib. This will be
>> the view that belongs to UIViewController. It is the
>> UIViewController base class that loads the nib. As long as it
>> retains that top level view then all the subviews will also be
>> retained. They should be released when the UIViewController
>> releases its view outlet.
>
> Right, and view is a property of UIViewController. When you have
> your UIViewController release view, that is an example of the
> programmer releasing an outlet assigned from IB, which you seem to
> be arguing that the programmer shouldn't have to release objects
> given to it from IB.
Top. Level. Object.
Whatever code loads the nib is the owner of the array of top level
objects and should retain them. That object is UIViewController, not
my subclass.
At any rate. The problem is that this is poorly documented.
--
Brian Stern
<brians99...> -
>>>> OK, this issue has come up for me very recently. It appears thatExactly - most of the things you're hooking up in IB are your own
>>>> on iPhoneOS IBOutlets are retained, regardless of the presence of
>>>> properties. Even worse, in the presence of an assign property the
>>>> outlet is still retained. Whatever code is retaining the outlets
>>>> never releases them. So it seems that client code must release
>>>> all outlets.
>>>
>>>
>>> Seems to me that the outlets must have a retain count of at least
>>> one when they're unarchived, as though they were alloc'd. It makes
>>> sense that the programmer should have to manually release objects
>>> in dealloc. How else would it happen?
>>
>>
>> IBOutlets are not necessarily top level objects. Most are simply
>> views that happen to be in the view hierarchy. There will typically
>> be one top level object in an iPhone nib. This will be the view
>> that belongs to UIViewController. It is the UIViewController base
>> class that loads the nib. As long as it retains that top level view
>> then all the subviews will also be retained. They should be
>> released when the UIViewController releases its view outlet.
>
>
> Right, and view is a property of UIViewController. When you have your
> UIViewController release view, that is an example of the programmer
> releasing an outlet assigned from IB, which you seem to be arguing
> that the programmer shouldn't have to release objects given to it
> from IB.
>
> Luke
>
objects, those outlets are just instance variables which are being set
for you. It's your object, you have to deal with the lifetimes of the
objects you refer to. I don't see why IB makes any difference, it's just
calling setFoo: on some instance of your class, what you define setFoo
to do is entirely up to you, but if it retains the argument, then you
have to release it one day, in dealloc() would be the natural place.
The iPhone version of nib unarchiving and hookup seemed very consistent
to me, it makes use of properties or setFoo: if you have them, allowing
you to manage objects any way you like.
Perhaps the new @property() syntax makes it easy to forget about object
lifetimes because it does the set/get/change automagically. These days
when I add any property I go right to the dealloc method (and init if I
have one) and ensure I've managed that property before I forget. -
On Nov 17, 2008, at 11:05 PM, Roland King wrote:
>
>>>>> OK, this issue has come up for me very recently. It appears
>>>>> that on iPhoneOS IBOutlets are retained, regardless of the
>>>>> presence of properties. Even worse, in the presence of an
>>>>> assign property the outlet is still retained. Whatever code is
>>>>> retaining the outlets never releases them. So it seems that
>>>>> client code must release all outlets.
>>>>
>>>>
>>>> Seems to me that the outlets must have a retain count of at
>>>> least one when they're unarchived, as though they were alloc'd.
>>>> It makes sense that the programmer should have to manually
>>>> release objects in dealloc. How else would it happen?
>>>
>>>
>>> IBOutlets are not necessarily top level objects. Most are simply
>>> views that happen to be in the view hierarchy. There will
>>> typically be one top level object in an iPhone nib. This will be
>>> the view that belongs to UIViewController. It is the
>>> UIViewController base class that loads the nib. As long as it
>>> retains that top level view then all the subviews will also be
>>> retained. They should be released when the UIViewController
>>> releases its view outlet.
>>
>>
>> Right, and view is a property of UIViewController. When you have
>> your UIViewController release view, that is an example of the
>> programmer releasing an outlet assigned from IB, which you seem to
>> be arguing that the programmer shouldn't have to release objects
>> given to it from IB.
>>
>> Luke
>>
> Exactly - most of the things you're hooking up in IB are your own
> objects, those outlets are just instance variables which are being
> set for you. It's your object, you have to deal with the lifetimes
> of the objects you refer to. I don't see why IB makes any
> difference, it's just calling setFoo: on some instance of your
> class, what you define setFoo to do is entirely up to you, but if it
> retains the argument, then you have to release it one day, in
> dealloc() would be the natural place.
>
> The iPhone version of nib unarchiving and hookup seemed very
> consistent to me, it makes use of properties or setFoo: if you have
> them, allowing you to manage objects any way you like.
>
> Perhaps the new @property() syntax makes it easy to forget about
> object lifetimes because it does the set/get/change automagically.
> These days when I add any property I go right to the dealloc method
> (and init if I have one) and ensure I've managed that property
> before I forget.
Yes, but this is exactly the point. If I have no property for an
Outlet it's still retained. If I have a property for an outlet that
is assign, and not retain the outlet is still retained, and I still
must release it, even though I never retained it.
When you say I can manage the outlets any way I like this is wrong.
They are managed for me. I want them to not be retained. I don't
have that option.
Now that I understand this I can live with it. But it still makes no
sense to me. -
On Nov 17, 2008, at 9:11 PM, mmalcolm crawford wrote:
> One other consideration, particularly in iPhone applications, is
> where you might have outlets to subviews of a main view that might
> be released in sime situations -- e.g. a UIViewController whose view
> is released in didReceiveMemoryWarning. To ensure that you don't
> prolong the lifetime of objects you got from the nib, you should set
> (use your accessor methods to) set those variables to nil in the
> relevant method, e.g.:
>
> @interface MyController : UIViewController {
> UILabel *label;
> ...
> }
> @property (nonatomic, retain) IBOutlet UILabel *label;
>
> then
>
> - (void)didReceiveMemoryWarning {
> self.label = nil;
> [super didReceiveMemoryWarning];
> }
I think it makes more sense to release the Outlets in viewDidLoad.
This way I only have to release them in one spot, not two. -
On Nov 17, 2008, at 8:15 PM, Brian Stern wrote:
> When you say I can manage the outlets any way I like this is wrong.
> They are managed for me. I want them to not be retained. I don't
> have that option.
I never said this. I compared having objects unarchived from a nib to
being alloc'd, where the retain count is initially set to 1.
Luke -
On Nov 17, 2008, at 8:17 PM, Brian Stern wrote:
> I think it makes more sense to release the Outlets in viewDidLoad.
Why would you be releasing outlets when the view just loaded?
Generally releasing happens when you're ready for something to go
away.... -
On Nov 17, 2008, at 11:20 PM, Luke the Hiesterman wrote:
>
> On Nov 17, 2008, at 8:17 PM, Brian Stern wrote:
>
>> I think it makes more sense to release the Outlets in viewDidLoad.
>
> Why would you be releasing outlets when the view just loaded?
> Generally releasing happens when you're ready for something to go
> away....
There is an extra retain on the Outlets. It is unneeded. The outlets
are sufficiently retained by the view hierarchy.
Either I have to release in both dealloc and in
didReceiveMemoryWarning, or I can have them in viewDidLoad.
Release also is sent when you transfer ownership of an object to
another object. I don't wish to have ownership of the outlets. They
can be owned by the view hierarchy. So if I release them in
viewDidLoad then I don't have to release them in two other places,
which is obviously error prone.
Don't you find it odd that you need to release outlets in
didReceiveMemoryWarning? -
>
> Yes, but this is exactly the point. If I have no property for an
> Outlet it's still retained. If I have a property for an outlet that
> is assign, and not retain the outlet is still retained, and I still
> must release it, even though I never retained it.
>
> When you say I can manage the outlets any way I like this is wrong.
> They are managed for me. I want them to not be retained. I don't
> have that option.
>
> Now that I understand this I can live with it. But it still makes no
> sense to me.
> _______________________________________________
That's not what the documentation says and it's not my experience
either. The documentation says (section titled NIB Object Retention)
that each object in the NIB file is created with a retain count of 1 and
then autoreleased. Then they are hooked up using setValue:forKey: which
uses the setter method if it exists. It also explicitly tells you that
if you don't retain the array of top-level objects you're going to lose
them.
So if you have an outlet which is assign, and the setter method is
correct, the object will be created with retain count of 1,
autoreleased, then the setter method will be called and assign it (no
retain) and you do not have to release it. Why do you think that you do?
I've done this, I have this exact patten in some of my iPhone code, I
have a delegate property which is assign and it is assigned and it goes
away when it's supposed to go away. -
On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
> On Nov 17, 2008, at 9:11 PM, mmalcolm crawford wrote:No, on iPhone outlets are consistently *not* retained -- which is
>
>> One other consideration, particularly in iPhone applications, is
>> where you might have outlets to subviews of a main view that might
>> be released in sime situations -- e.g. a UIViewController whose
>> view is released in didReceiveMemoryWarning. To ensure that you
>> don't prolong the lifetime of objects you got from the nib, you
>> should set (use your accessor methods to) set those variables to
>> nil in the relevant method, e.g.:
>>
>> @interface MyController : UIViewController {
>> UILabel *label;
>> ...
>> }
>> @property (nonatomic, retain) IBOutlet UILabel *label;
>>
>> then
>>
>> - (void)didReceiveMemoryWarning {
>> self.label = nil;
>> [super didReceiveMemoryWarning];
>> }
>
> OK, this issue has come up for me very recently. It appears that on
> iPhoneOS IBOutlets are retained, regardless of the presence of
> properties.
>
precisely why you do need to retain top-level objects on iPhone. But
absent accessor methods, connections are made using KVC...
This is documented here:
<http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Lo
adingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000
051i-CH4-SW6>
> Even worse, in the presence of an assign property the outlet isAs I stated originally, following the pattern I describe above makes
> still retained. Whatever code is retaining the outlets never
> releases them. So it seems that client code must release all outlets.
>
memory management consistent in all situations.
> The documentation on this is vague, with a lot of 'should's and not
> clear statements of what really happens.
>
The documentation at <http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Lo
adingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000
051i-CH4-SW6> is explicit, there are just many different situations to consider
if you don't follow the property pattern.
mmalc
> Actually this isn't (only) related to didReceiveMemoryWarning (which
> I hadn't considered related to this problem until you raised it).
-
On Nov 17, 2008, at 11:35 PM, Roland King wrote:
>
>>
>> Yes, but this is exactly the point. If I have no property for an
>> Outlet it's still retained. If I have a property for an outlet
>> that is assign, and not retain the outlet is still retained, and I
>> still must release it, even though I never retained it.
>>
>> When you say I can manage the outlets any way I like this is
>> wrong. They are managed for me. I want them to not be retained.
>> I don't have that option.
>>
>> Now that I understand this I can live with it. But it still makes
>> no sense to me.
>> _______________________________________________
>
> That's not what the documentation says and it's not my experience
> either. The documentation says (section titled NIB Object Retention)
> that each object in the NIB file is created with a retain count of 1
> and then autoreleased. Then they are hooked up using
> setValue:forKey: which uses the setter method if it exists. It also
> explicitly tells you that if you don't retain the array of top-level
> objects you're going to lose them.
>
> So if you have an outlet which is assign, and the setter method is
> correct, the object will be created with retain count of 1,
> autoreleased, then the setter method will be called and assign it
> (no retain) and you do not have to release it. Why do you think that
> you do?
>
> I've done this, I have this exact patten in some of my iPhone code,
> I have a delegate property which is assign and it is assigned and it
> goes away when it's supposed to go away.
OK. The reason I believe that is because I fixed a massive memory
leak a couple days ago that I tracked down to this issue. I built a
simple test application that demonstrates that outlets that have no
properties or have assign properties are retained anyway and must be
released.
Here's my test project:
http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
There are three labels that are outlets. One has a retain property,
one an assign property, and the third no property. Unless they are
released they are never dealloced. All three act the same.
--
Brian Stern
<brians99...> -
On Nov 17, 2008, at 8:05 PM, Roland King wrote:
> The iPhone version of nib unarchiving and hookup seemed veryThis applies to both iPhone and Mac OS X/desktop.
> consistent to me, it makes use of properties or setFoo: if you have
> them, allowing you to manage objects any way you like.
>
This is why using properties simplifies matters...
mmalc -
On Nov 17, 2008, at 8:17 PM, Brian Stern wrote:
> I think it makes more sense to release the Outlets in viewDidLoad.No, it doesn't.
> This way I only have to release them in one spot, not two.
>
There is no sense at all in releasing outlets in viewDidLoad.
Follow the pattern I described and it's consistent...
mmalc -
On Nov 17, 2008, at 8:34 PM, Brian Stern wrote:
> Don't you find it odd that you need to release outlets inNot at all -- assuming that you have a reference -- strong or weak --
> didReceiveMemoryWarning?
>
to an item in the user interface, you want to make sure you break it
if the view is supposed to disappear.
If you have a strong reference you want to make sure that the item is
disposed of when the other items from the nib go away; if you have a
weak reference you want to make sure you don't send a message to a
deallocated object (it'll go when the view goes...).
mmalc -
On Nov 17, 2008, at 11:58 PM, mmalcolm crawford wrote:
>
> On Nov 17, 2008, at 8:34 PM, Brian Stern wrote:
>
>> Don't you find it odd that you need to release outlets in
>> didReceiveMemoryWarning?
>>
> Not at all -- assuming that you have a reference -- strong or weak
> -- to an item in the user interface, you want to make sure you break
> it if the view is supposed to disappear.
> If you have a strong reference you want to make sure that the item
> is disposed of when the other items from the nib go away; if you
> have a weak reference you want to make sure you don't send a message
> to a deallocated object (it'll go when the view goes...).
UIViewController isn't guaranteed to release the view. It only does
this if the view isn't visible, based on its own heuristics. My
subclass has no real way to know if the view will be released or not.
If I release the outlets in viewDidLoad then I don't have this
problem. My code has no interest in maintaining a strong reference to
its outlets. The view hierarchy can do that just fine.
--
Brian Stern
<brians99...> -
On Nov 17, 2008, at 11:51 PM, mmalcolm crawford wrote:
>> >
> On Nov 17, 2008, at 7:12 PM, Brian Stern wrote:
>
>> On Nov 17, 2008, at 9:11 PM, mmalcolm crawford wrote:
>>
>>> One other consideration, particularly in iPhone applications, is
>>> where you might have outlets to subviews of a main view that might
>>> be released in sime situations -- e.g. a UIViewController whose
>>> view is released in didReceiveMemoryWarning. To ensure that you
>>> don't prolong the lifetime of objects you got from the nib, you
>>> should set (use your accessor methods to) set those variables to
>>> nil in the relevant method, e.g.:
>>>
>>> @interface MyController : UIViewController {
>>> UILabel *label;
>>> ...
>>> }
>>> @property (nonatomic, retain) IBOutlet UILabel *label;
>>>
>>> then
>>>
>>> - (void)didReceiveMemoryWarning {
>>> self.label = nil;
>>> [super didReceiveMemoryWarning];
>>> }
>>
>> OK, this issue has come up for me very recently. It appears that
>> on iPhoneOS IBOutlets are retained, regardless of the presence of
>> properties.
>>
> No, on iPhone outlets are consistently *not* retained -- which is
> precisely why you do need to retain top-level objects on iPhone. But
> absent accessor methods, connections are made using KVC...
> This is documented here:
> <http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Lo
adingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000
051i-CH4-SW6
That's the vague documentation that I referred to. What you're
telling me is that where it says should in that paragraph it really
means must. OK, that's what I figured out a few days ago.
Where it says that it "retains the object by default if no setter
method is available", that seems to contradict what you say about
outlets not being retained. Actually I didn't really absorb that
statement before. It means that if there's no property then the
outlet will be retained. OK.
My experience with the assign property is contrary to what the docs
seem to be saying. I think the outlet is retained even if there is an
assign property.
> As I stated originally, following the pattern I describe above makes
> memory management consistent in all situations.
I simply don't need properties for all my Outlets, except for this
issue. I also don't really like making all my outlets implicitly
public. But I'm forced to do that.
--
Brian Stern
<brians99...> -
Brian Stern wrote:
>I'm a bit limited at work, no Mac here, so I took a look with wordpad ..
> On Nov 17, 2008, at 11:35 PM, Roland King wrote:
>
>>
>>>
>>> Yes, but this is exactly the point. If I have no property for an
>>> Outlet it's still retained. If I have a property for an outlet
>>> that is assign, and not retain the outlet is still retained, and I
>>> still must release it, even though I never retained it.
>>>
>>> When you say I can manage the outlets any way I like this is
>>> wrong. They are managed for me. I want them to not be retained.
>>> I don't have that option.
>>>
>>> Now that I understand this I can live with it. But it still makes
>>> no sense to me.
>>> _______________________________________________
>>
>>
>> That's not what the documentation says and it's not my experience
>> either. The documentation says (section titled NIB Object Retention)
>> that each object in the NIB file is created with a retain count of 1
>> and then autoreleased. Then they are hooked up using
>> setValue:forKey: which uses the setter method if it exists. It also
>> explicitly tells you that if you don't retain the array of top-level
>> objects you're going to lose them.
>>
>> So if you have an outlet which is assign, and the setter method is
>> correct, the object will be created with retain count of 1,
>> autoreleased, then the setter method will be called and assign it
>> (no retain) and you do not have to release it. Why do you think that
>> you do?
>>
>> I've done this, I have this exact patten in some of my iPhone code,
>> I have a delegate property which is assign and it is assigned and it
>> goes away when it's supposed to go away.
>
>
>
> OK. The reason I believe that is because I fixed a massive memory
> leak a couple days ago that I tracked down to this issue. I built a
> simple test application that demonstrates that outlets that have no
> properties or have assign properties are retained anyway and must be
> released.
>
> Here's my test project:
>
> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
>
>
> There are three labels that are outlets. One has a retain property,
> one an assign property, and the third no property. Unless they are
> released they are never dealloced. All three act the same.
>
how nice.
You've defined the actual label pointers as IBOutlet, like this
IBOutlet MyLabel* mLabel1;
and then called the properties label1 etc.
in your .h file. When you hook them up in IB (I can't open that here so
I'm afraid I can't look) what is the name of the thing you bind to,
label1 or mLabel1? I think you'll find it's mLabel1 right? I believe
what you're doing is accessing the variables DIRECTLY in each binding
because you have defined those at outlets, not the properties, and in
that case yes they get retained as you know and as the documentation says.
What I think you wanted was this
MyLabel *mLabel1;
@property( nonatomic, assign ) IBOutlet MyLabel *label1;
to define the PROPERTY as the outlet, not the variable.
I think if you'd written your own setters/getters instead of
synthesizing them, as I sometimes do when I really don't know who the
hell is calling me and when, you'd find they didn't get called. I
sometimes think that |accessInstanceVariablesDirectly is evil and should
be turned off.
I started off using properties and calling them something different from
variables because I was paranoid I'd access them directly, I've sort of
stopped that now as I mostly remember not to do that, but I can
understand why you'd want them differently named.
Roland
| -
On Nov 17, 2008, at 8:53 PM, Brian Stern wrote:
> Here's my test project:It would help if you declared/connected your outlets correctly...
> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
> There are three labels that are outlets. One has a retain property,
> one an assign property, and the third no property. Unless they are
> released they are never dealloced. All three act the same.
>
If you declare a property:
@property (nonatomic, assign) MyLabel *label1;
but make the connection in IB to mLabel1, then the property accessor
isn't used. So the outlet is set using setValue:forKey:. Which
results in the value being retained, precisely as described in the
documentation...
<http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Lo
adingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000
051i-CH4-SW6>
If you declare the the properties as I described:
@interface ViewControllerOne : UIViewController
{
MyLabel* mLabel1;
MyLabel* mLabel2;
IBOutlet MyLabel* mLabel3;
}
@property (nonatomic, assign) IBOutlet MyLabel *mLabel1;
@property (nonatomic, retain) IBOutlet MyLabel *mLabel2;
// No property for label3
then you'll get the behaviour I described...
mmalc -
On Nov 17, 2008, at 9:10 PM, Brian Stern wrote:
> I simply don't need properties for all my Outlets, except for this
> issue. I also don't really like making all my outlets implicitly
> public. But I'm forced to do that.
You can use the readonly option for your properties. Alternatively,
you can can declare a private setter. -
On Nov 17, 2008, at 9:11 PM, Roland King wrote:
> I'm a bit limited at work, no Mac here, so I took a look with
> wordpad .. how nice.
>
> You've defined the actual label pointers as IBOutlet, like this
>
> IBOutlet MyLabel* mLabel1;
>
> and then called the properties label1 etc.
>
> in your .h file. When you hook them up in IB (I can't open that here
> so I'm afraid I can't look) what is the name of the thing you bind
> to, label1 or mLabel1? I think you'll find it's mLabel1 right? I
> believe what you're doing is accessing the variables DIRECTLY in
> each binding because you have defined those at outlets, not the
> properties, and in that case yes they get retained as you know and
> as the documentation says.
Roland is correct. You've hooked up IB directly to the instance
variables. -
On Nov 18, 2008, at 12:11 AM, Roland King wrote:
> Brian Stern wrote:
>
>>
>> On Nov 17, 2008, at 11:35 PM, Roland King wrote:
>>
>>>
>>>>
>>>> Yes, but this is exactly the point. If I have no property for
>>>> an Outlet it's still retained. If I have a property for an
>>>> outlet that is assign, and not retain the outlet is still
>>>> retained, and I still must release it, even though I never
>>>> retained it.
>>>>
>>>> When you say I can manage the outlets any way I like this is
>>>> wrong. They are managed for me. I want them to not be
>>>> retained. I don't have that option.
>>>>
>>>> Now that I understand this I can live with it. But it still
>>>> makes no sense to me.
>>>> _______________________________________________
>>>
>>>
>>> That's not what the documentation says and it's not my experience
>>> either. The documentation says (section titled NIB Object
>>> Retention) that each object in the NIB file is created with a
>>> retain count of 1 and then autoreleased. Then they are hooked up
>>> using setValue:forKey: which uses the setter method if it exists.
>>> It also explicitly tells you that if you don't retain the array
>>> of top-level objects you're going to lose them.
>>>
>>> So if you have an outlet which is assign, and the setter method
>>> is correct, the object will be created with retain count of 1,
>>> autoreleased, then the setter method will be called and assign it
>>> (no retain) and you do not have to release it. Why do you think
>>> that you do?
>>>
>>> I've done this, I have this exact patten in some of my iPhone
>>> code, I have a delegate property which is assign and it is
>>> assigned and it goes away when it's supposed to go away.
>>
>>
>>
>> OK. The reason I believe that is because I fixed a massive memory
>> leak a couple days ago that I tracked down to this issue. I built
>> a simple test application that demonstrates that outlets that have
>> no properties or have assign properties are retained anyway and
>> must be released.
>>
>> Here's my test project:
>>
>> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
>>
>> There are three labels that are outlets. One has a retain
>> property, one an assign property, and the third no property.
>> Unless they are released they are never dealloced. All three act
>> the same.
>>
> in your .h file. When you hook them up in IB (I can't open that here
> so I'm afraid I can't look) what is the name of the thing you bind
> to, label1 or mLabel1? I think you'll find it's mLabel1 right? I
> believe what you're doing is accessing the variables DIRECTLY in
> each binding because you have defined those at outlets, not the
> properties, and in that case yes they get retained as you know and
> as the documentation says.
>
> What I think you wanted was this
>
> MyLabel *mLabel1;
>
> @property( nonatomic, assign ) IBOutlet MyLabel *label1;
>
> to define the PROPERTY as the outlet, not the variable.
>
You're right. I guess I didn't know there was a difference in the
semantics based on the position of the IBOutlet.
In the end though I'm still pretty much forced to have properties for
these outlets even though I don't want them.
--
Brian Stern
<brians99...> -
> If you declare a property:<http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptu>
>
> @property (nonatomic, assign) MyLabel *label1;
>
> but make the connection in IB to mLabel1, then the property accessor
> isn't used. So the outlet is set using setValue:forKey:. Which
> results in the value being retained, precisely as described in the
> documentation...
>
>
al/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/
> uid/10000051i-CH4-SW6
How about:
http://developer.apple.com/samplecode/CacheInfo-MacOSX/listing1.html
(for example) which has the IBOutlet tag on the instance variables
rather than the properties; I'll bet its different because properties
and instance vars have the same name, isn't it?
(Note, this isn't the only one I've seen this pattern in, its just the
first that came to hand)
That example declares dozens of IBOutlet's, whose properties are
(nonatomic,retain) and doesn't release any of them in its dealloc. -
On Nov 17, 2008, at 10:12 PM, Brian Stern wrote:
>
> On Nov 17, 2008, at 9:11 PM, mmalcolm crawford wrote:
>
>> One other consideration, particularly in iPhone applications, is
>> where you might have outlets to subviews of a main view that might
>> be released in sime situations -- e.g. a UIViewController whose
>> view is released in didReceiveMemoryWarning. To ensure that you
>> don't prolong the lifetime of objects you got from the nib, you
>> should set (use your accessor methods to) set those variables to
>> nil in the relevant method, e.g.:
>>
>> @interface MyController : UIViewController {
>> UILabel *label;
>> ...
>> }
>> @property (nonatomic, retain) IBOutlet UILabel *label;
>>
>> then
>>
>> - (void)didReceiveMemoryWarning {
>> self.label = nil;
>> [super didReceiveMemoryWarning];
>> }
>
> OK, this issue has come up for me very recently. It appears that on
> iPhoneOS IBOutlets are retained, regardless of the presence of
> properties.
> Even worse, in the presence of an assign property the outlet is
> still retained. Whatever code is retaining the outlets never
> releases them. So it seems that client code must release all outlets.
The above statements are not true. On the iPhone, outlets are
connected with setValue:forKeyPath:, and no explicit retention is done
by the NIB unarchiving code. It maybe true that the objects are
retained in some other fashion, independent of outlets. For example,
when the MainWindow.nib is loaded by UIApplication, UIApplication
explicitly retains the returned top level objects. That's a property
of UIApplication, and doesn't really have anything to do with NIB
loading in general. In the future, other nib loading classes may
choose to do the same thing. If this is the situation you're referring
to, and you're sending your outlet objects an extra release message,
you're over releasing them.
The solution to a memory leak should never be an unbalanced release.
You should use instruments and object alloc to determine exactly where
the unbalanced retain is, and then balance it correctly. If you find a
leak in framework code, you should file a bug, and you may consider
over releasing it on your end for ballence, but if you choose to do
that, you should do it with extreme caution. If there really is a leak
in the framework code, then when it's fixed, you're unbalanced
releases will start causing crashes.
> The documentation on this is vague, with a lot of 'should's and not
> clear statements of what really happens.
If you ask specific questions about specific pieces of documentation,
I'm sure that many readers would be happy to help you.
Jon Hess
> Actually this isn't (only) related to didReceiveMemoryWarning (which
> I hadn't considered related to this problem until you raised it).
>
> Is this the way that things are supposed to work on iPhone OS?
>
>
> --
> Brian Stern
> <brians99...>
-
On Nov 18, 2008, at 12:13 AM, mmalcolm crawford wrote:
>
> On Nov 17, 2008, at 8:53 PM, Brian Stern wrote:
>
>> Here's my test project:
>> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
>> There are three labels that are outlets. One has a retain
>> property, one an assign property, and the third no property.
>> Unless they are released they are never dealloced. All three act
>> the same.
>>
> It would help if you declared/connected your outlets correctly...
>
> //...
>
> then you'll get the behaviour I described...
OK, fair enough.
You didn't address my other point regarding the memory warnings. If
the view controller is visible then it won't release the view
hierarchy. Your suggested code will null the outlet even though it
still exists, resulting in bugs in some cases.
--
Brian Stern
<brians99...> -
>> Perhaps the new @property() syntax makes it easy to forget about
>> object lifetimes because it does the set/get/change automagically.
>> These days when I add any property I go right to the dealloc method
>> (and init if I have one) and ensure I've managed that property
>> before I forget.
>
> Yes, but this is exactly the point. If I have no property for an
> Outlet it's still retained.
Hey Brian -
Outlets for iPhone OS are established by calling setValue:forKeyPath:.
The behavior of setValue:forKeyPath: is that if a setter exists, it is
called. If a setter does not exist, the instance variable is looked up
and set directly, and if it is an object, it is retained. This means
that for IBOutlets, with no setters, they're retained in iPhone OS.
This is different from Mac OS X. If you're writing code on both
platforms, or are planning to, you should always use properties on
both platforms since it makes the decision to retain outlets explicit
and obvious.
Jon Hess -
On Nov 18, 2008, at 1:11 PM, Roland King wrote:
> Brian Stern wrote:
>
>>
>> On Nov 17, 2008, at 11:35 PM, Roland King wrote:
>>
>>>
>>>>
>>>> Yes, but this is exactly the point. If I have no property for
>>>> an Outlet it's still retained. If I have a property for an
>>>> outlet that is assign, and not retain the outlet is still
>>>> retained, and I still must release it, even though I never
>>>> retained it.
>>>>
>>>> When you say I can manage the outlets any way I like this is
>>>> wrong. They are managed for me. I want them to not be
>>>> retained. I don't have that option.
>>>>
>>>> Now that I understand this I can live with it. But it still
>>>> makes no sense to me.
>>>> _______________________________________________
>>>
>>>
>>> That's not what the documentation says and it's not my experience
>>> either. The documentation says (section titled NIB Object
>>> Retention) that each object in the NIB file is created with a
>>> retain count of 1 and then autoreleased. Then they are hooked up
>>> using setValue:forKey: which uses the setter method if it exists.
>>> It also explicitly tells you that if you don't retain the array
>>> of top-level objects you're going to lose them.
>>>
>>> So if you have an outlet which is assign, and the setter method
>>> is correct, the object will be created with retain count of 1,
>>> autoreleased, then the setter method will be called and assign it
>>> (no retain) and you do not have to release it. Why do you think
>>> that you do?
>>>
>>> I've done this, I have this exact patten in some of my iPhone
>>> code, I have a delegate property which is assign and it is
>>> assigned and it goes away when it's supposed to go away.
>>
>>
>>
>> OK. The reason I believe that is because I fixed a massive memory
>> leak a couple days ago that I tracked down to this issue. I built
>> a simple test application that demonstrates that outlets that have
>> no properties or have assign properties are retained anyway and
>> must be released.
>>
>> Here's my test project:
>>
>> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
>>
>> There are three labels that are outlets. One has a retain
>> property, one an assign property, and the third no property.
>> Unless they are released they are never dealloced. All three act
>> the same.
>>
> I'm a bit limited at work, no Mac here, so I took a look with
> wordpad .. how nice.
>
> You've defined the actual label pointers as IBOutlet, like this
>
> IBOutlet MyLabel* mLabel1;
>
> and then called the properties label1 etc.
>
> in your .h file. When you hook them up in IB (I can't open that here
> so I'm afraid I can't look) what is the name of the thing you bind
> to, label1 or mLabel1? I think you'll find it's mLabel1 right? I
> believe what you're doing is accessing the variables DIRECTLY in
> each binding because you have defined those at outlets, not the
> properties, and in that case yes they get retained as you know and
> as the documentation says.
>
> What I think you wanted was this
>
> MyLabel *mLabel1;
>
> @property( nonatomic, assign ) IBOutlet MyLabel *label1;
>
> to define the PROPERTY as the outlet, not the variable.
>
> I think if you'd written your own setters/getters instead of
> synthesizing them, as I sometimes do when I really don't know who
> the hell is calling me and when, you'd find they didn't get called.
> I sometimes think that |accessInstanceVariablesDirectly is evil and
> should be turned off.
>
> I started off using properties and calling them something different
> from variables because I was paranoid I'd access them directly, I've
> sort of stopped that now as I mostly remember not to do that, but I
> can understand why you'd want them differently named.
Normally instance variables and properties share the same name, so it
doesn't matter to Interface Builder where the 'IBOutlet' text appears.
If you're going to give your instance variables different names
though, you need to put the IBOutlet qualifier on the property if you
want it to be used.
In the above example, Interface Builder is going to use '[obj
setValue:someLabel forKeyPath:@"mLabel"]' which won't result in the
setter being used. The problem is the 'mLabel' for the keyPath instead
of 'label'.
The only thing that determines if Interface Builder uses a setter, or
accesses iVars directly is the presence of the setter, and the name of
the outlet. The name of the outlet is used as the keyPath in
setValue:forKeyPath:. The name of the outlet is the name of the
property or instance variable the IBOutlet modifier appears next to.
Interface Builder always calls setValue:forKeyPath:.
Jon Hess
>
>
> Roland
> |
-
On Nov 18, 2008, at 12:34 AM, Jonathan Hess wrote:
>
> The solution to a memory leak should never be an unbalanced release.
What I did to fix this was to add all of the properties to all of the
outlets so they'd all be retained through those properties. Then I
added all the releases to all the deallocs to match those retains.
--
Brian Stern
<brians99...> -
> I simply don't need properties for all my Outlets, except for this
> issue. I also don't really like making all my outlets implicitly
> public. But I'm forced to do that.
Here's one way to avoid making your outlets public:
// Header
@interface MyClass : NSObject {
@private
IBOutlet UILabel *myLabel;
}
@end
// Implementation
@implementation MyClass
- (void)setMyLabel:(UILabel *)myLabel {
myLabel = label;
}
@end
You get non-retained outlets, and it's still explicit and obvious. You
can create many other variations of this. For example, you can use
@property and @synthesize in only the implementation file. The most
important thing to remember is that IB calls setValue:forKeyPath: with
a key path that is equal to the name of your outlet. You can read
about key value coding here: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Ke
yValueCoding.html
Compiled in mail -
Jon Hess -
On Nov 18, 2008, at 12:32 AM, Brian Stern wrote:
>
> On Nov 18, 2008, at 12:11 AM, Roland King wrote:
>
>> Brian Stern wrote:
>>
>>>
>>> On Nov 17, 2008, at 11:35 PM, Roland King wrote:
>>>
>>>>
>>>>>
>>>>> Yes, but this is exactly the point. If I have no property for
>>>>> an Outlet it's still retained. If I have a property for an
>>>>> outlet that is assign, and not retain the outlet is still
>>>>> retained, and I still must release it, even though I never
>>>>> retained it.
>>>>>
>>>>> When you say I can manage the outlets any way I like this is
>>>>> wrong. They are managed for me. I want them to not be
>>>>> retained. I don't have that option.
>>>>>
>>>>> Now that I understand this I can live with it. But it still
>>>>> makes no sense to me.
>>>>> _______________________________________________
>>>>
>>>>
>>>> That's not what the documentation says and it's not my
>>>> experience either. The documentation says (section titled NIB
>>>> Object Retention) that each object in the NIB file is created
>>>> with a retain count of 1 and then autoreleased. Then they are
>>>> hooked up using setValue:forKey: which uses the setter method if
>>>> it exists. It also explicitly tells you that if you don't retain
>>>> the array of top-level objects you're going to lose them.
>>>>
>>>> So if you have an outlet which is assign, and the setter method
>>>> is correct, the object will be created with retain count of 1,
>>>> autoreleased, then the setter method will be called and assign
>>>> it (no retain) and you do not have to release it. Why do you
>>>> think that you do?
>>>>
>>>> I've done this, I have this exact patten in some of my iPhone
>>>> code, I have a delegate property which is assign and it is
>>>> assigned and it goes away when it's supposed to go away.
>>>
>>>
>>>
>>> OK. The reason I believe that is because I fixed a massive
>>> memory leak a couple days ago that I tracked down to this issue.
>>> I built a simple test application that demonstrates that outlets
>>> that have no properties or have assign properties are retained
>>> anyway and must be released.
>>>
>>> Here's my test project:
>>>
>>> http://bellsouthpwp2.net/b/r/brians99/projects/TestPropertiesAndOutlets.zip
>>>
>>> There are three labels that are outlets. One has a retain
>>> property, one an assign property, and the third no property.
>>> Unless they are released they are never dealloced. All three act
>>> the same.
>>>
>> in your .h file. When you hook them up in IB (I can't open that
>> here so I'm afraid I can't look) what is the name of the thing you
>> bind to, label1 or mLabel1? I think you'll find it's mLabel1 right?
>> I believe what you're doing is accessing the variables DIRECTLY in
>> each binding because you have defined those at outlets, not the
>> properties, and in that case yes they get retained as you know and
>> as the documentation says.
>>
>> What I think you wanted was this
>>
>> MyLabel *mLabel1;
>>
>> @property( nonatomic, assign ) IBOutlet MyLabel *label1;
>>
>> to define the PROPERTY as the outlet, not the variable.
>>
>
> You're right. I guess I didn't know there was a difference in the
> semantics based on the position of the IBOutlet.
I know I'm repeating myself, but I just want to be clear. The problem
here isn't the position of 'IBOutlet' the problem is that the instance
variable and property have different names. Referring to the outlet
'mLabel' is different than referring to the outlet 'label'. One will
result in looking for a setter called 'setMLabel:' and the other will
result in looking for a setter named 'setLabel:' If the property and
the instance variable had the same name, it wouldn't matter where you
placed the IBOutlet modifier.
Jon Hess
>
>
> In the end though I'm still pretty much forced to have properties
> for these outlets even though I don't want them.
>
>
> --
> Brian Stern
> <brians99...>
-
On Nov 18, 2008, at 12:35 AM, Jonathan Hess wrote:
>
> Normally instance variables and properties share the same name,
Normally in your code maybe, not mine.
> so it doesn't matter to Interface Builder where the 'IBOutlet' text
> appears. If you're going to give your instance variables different
> names though, you need to put the IBOutlet qualifier on the property
> if you want it to be used.
I guess I just had a perfect storm of issues that made it appear that
things were working differently from the way they were working. My
properties, though present, were ignored. The fact that it works
differently from Mac OS makes it worse.
Thanks for the help guys.
--
Brian Stern
<brians99...> -
On Nov 18, 2008, at 12:35 AM, Jonathan Hess wrote:
>>> Perhaps the new @property() syntax makes it easy to forget about
>>> object lifetimes because it does the set/get/change automagically.
>>> These days when I add any property I go right to the dealloc
>>> method (and init if I have one) and ensure I've managed that
>>> property before I forget.
>>
>> Yes, but this is exactly the point. If I have no property for an
>> Outlet it's still retained.
>
> Hey Brian -
>
> Outlets for iPhone OS are established by calling
> setValue:forKeyPath:. The behavior of setValue:forKeyPath: is that
> if a setter exists, it is called. If a setter does not exist, the
> instance variable is looked up and set directly, and if it is an
> object, it is retained. This means that for IBOutlets, with no
> setters, they're retained in iPhone OS. This is different from Mac
> OS X. If you're writing code on both platforms, or are planning to,
> you should always use properties on both platforms since it makes
> the decision to retain outlets explicit and obvious.
How come the documentation that mmalc quoted doesn't have this clear
statement?
>
>
> Jon Hess
--
Brian Stern
<brians99...> -
On Nov 18, 2008, at 12:43 AM, Brian Stern wrote:
>
> On Nov 18, 2008, at 12:34 AM, Jonathan Hess wrote:
>
>>
>> The solution to a memory leak should never be an unbalanced release.
>
> What I did to fix this was to add all of the properties to all of
> the outlets so they'd all be retained through those properties.
> Then I added all the releases to all the deallocs to match those
> retains.
From the later messages in this thread, it looks you didn't insert an
unbalanced retain after all. The retains and releases were balanced,
but the code wasn't executing as expected because the setters weren't
being used because the outlets had different names than the properties.
If you do encounter a leak like this in the future, please head my
advice. Inserting a unbalanced retain or release might fix a symptom,
but is likely to come back up as a hard to debug problem in the future.
Good Luck -
Jon Hess
>
>
> --
> Brian Stern
> <brians99...>
-
>>
>> Hey Brian -
>>
>> Outlets for iPhone OS are established by calling
>> setValue:forKeyPath:. The behavior of setValue:forKeyPath: is that
>> if a setter exists, it is called. If a setter does not exist, the
>> instance variable is looked up and set directly, and if it is an
>> object, it is retained. This means that for IBOutlets, with no
>> setters, they're retained in iPhone OS. This is different from Mac
>> OS X. If you're writing code on both platforms, or are planning to,
>> you should always use properties on both platforms since it makes
>> the decision to retain outlets explicit and obvious.
>
>
> How come the documentation that mmalc quoted doesn't have this clear
> statement?
which one did he quote, the one I suggested to you has it .. it's under
Nib Object Retention. It's a page I have bookmarked because as I switch
between iPhone and regular OSX I like to remind myself what it says.
It's pasted below.
iPhone OS - managed memory model
Objects in the nib file are created with a retain count of 1 and then
autoreleased. As it rebuilds the object hierarchy, however, UIKit
reestablishes connections between the objects using the
|setValue:forKey:| method, which uses the available setter method or
retains the object by default if no setter method is available. If you
define outlets for nib-file objects, you should also define a setter
method for accessing that outlet. Setter methods for outlets should
retain their values, and setter methods for outlets containing top-level
objects must retain their values to prevent them from being deallocated.
If you do not store the top-level objects in outlets, you must retain
either the array returned by the |loadNibNamed:owner:options:| method or
the objects inside the array to prevent those objects from being
released prematurely. -
On Nov 18, 2008, at 12:49 AM, Brian Stern wrote:
>
> On Nov 18, 2008, at 12:35 AM, Jonathan Hess wrote:
>>
>> Normally instance variables and properties share the same name,
>
> Normally in your code maybe, not mine.
>
>> so it doesn't matter to Interface Builder where the 'IBOutlet' text
>> appears. If you're going to give your instance variables different
>> names though, you need to put the IBOutlet qualifier on the
>> property if you want it to be used.
>
> I guess I just had a perfect storm of issues that made it appear
> that things were working differently from the way they were
> working. My properties, though present, were ignored. The fact that
> it works differently from Mac OS makes it worse.
Which difference are you referring to? It sounds like you're referring
to the fact that if a setter doesn't exist the variable is retained by
setValue:forKeyPath:. To avoid implementing setters, you're free to
them out and let IB directly set you're iVars. If you do that, you'll
just need to release them in dealloc. The best practices are there to
help developers who are new to both platforms. If you feel that you
have an adequate understanding of how the outlets are established,
you're free to use a pattern that you prefer.
Jon Hess
>
>
> Thanks for the help guys.
>
> --
> Brian Stern
> <brians99...>
-
On Nov 18, 2008, at 12:49 AM, Brian Stern wrote:
>
> On Nov 18, 2008, at 12:35 AM, Jonathan Hess wrote:
>
>>>> Perhaps the new @property() syntax makes it easy to forget about
>>>> object lifetimes because it does the set/get/change
>>>> automagically. These days when I add any property I go right to
>>>> the dealloc method (and init if I have one) and ensure I've
>>>> managed that property before I forget.
>>>
>>> Yes, but this is exactly the point. If I have no property for an
>>> Outlet it's still retained.
>>
>> Hey Brian -
>>
>> Outlets for iPhone OS are established by calling
>> setValue:forKeyPath:. The behavior of setValue:forKeyPath: is that
>> if a setter exists, it is called. If a setter does not exist, the
>> instance variable is looked up and set directly, and if it is an
>> object, it is retained. This means that for IBOutlets, with no
>> setters, they're retained in iPhone OS. This is different from Mac
>> OS X. If you're writing code on both platforms, or are planning to,
>> you should always use properties on both platforms since it makes
>> the decision to retain outlets explicit and obvious.
>
> How come the documentation that mmalc quoted doesn't have this clear
> statement?
Hey Brian -
Check out "Table 2-1". It states all of this explicitly.
Jon Hess
>
>
>
>>
>>
>> Jon Hess
>
> --
> Brian Stern
> <brians99...>
-
On Nov 18, 2008, at 1:00 AM, Jonathan Hess wrote:
>
> On Nov 18, 2008, at 12:49 AM, Brian Stern wrote:
>
>>
>> On Nov 18, 2008, at 12:35 AM, Jonathan Hess wrote:
>>>
>>> Normally instance variables and properties share the same name,
>>
>> Normally in your code maybe, not mine.
>>
>>> so it doesn't matter to Interface Builder where the 'IBOutlet'
>>> text appears. If you're going to give your instance variables
>>> different names though, you need to put the IBOutlet qualifier on
>>> the property if you want it to be used.
>>
>> I guess I just had a perfect storm of issues that made it appear
>> that things were working differently from the way they were
>> working. My properties, though present, were ignored. The fact
>> that it works differently from Mac OS makes it worse.
>
> Which difference are you referring to? It sounds like you're
> referring to the fact that if a setter doesn't exist the variable is
> retained by setValue:forKeyPath:.
Yes, that's the one.
> To avoid implementing setters, you're free to them out and let IB
> directly set you're iVars. If you do that, you'll just need to
> release them in dealloc. The best practices are there to help
> developers who are new to both platforms. If you feel that you have
> an adequate understanding of how the outlets are established, you're
> free to use a pattern that you prefer.
I understand it better now.
--
Brian Stern
<brians99...> -
On Nov 18, 2008, at 12:59 AM, Roland King wrote:
>
>>>
>>> Hey Brian -
>>>
>>> Outlets for iPhone OS are established by calling
>>> setValue:forKeyPath:. The behavior of setValue:forKeyPath: is
>>> that if a setter exists, it is called. If a setter does not
>>> exist, the instance variable is looked up and set directly, and
>>> if it is an object, it is retained. This means that for
>>> IBOutlets, with no setters, they're retained in iPhone OS. This
>>> is different from Mac OS X. If you're writing code on both
>>> platforms, or are planning to, you should always use properties
>>> on both platforms since it makes the decision to retain outlets
>>> explicit and obvious.
>>
>>
>> How come the documentation that mmalc quoted doesn't have this
>> clear statement?
>
>
> which one did he quote, the one I suggested to you has it .. it's
> under Nib Object Retention. It's a page I have bookmarked because as
> I switch between iPhone and regular OSX I like to remind myself what
> it says. It's pasted below.
Yes, that's it. I've read it plenty of times.
>
>
> iPhone OS - managed memory model
>
> Objects in the nib file are created with a retain count of 1 and
> then autoreleased. As it rebuilds the object hierarchy, however,
> UIKit reestablishes connections between the objects using the |
> setValue:forKey:| method, which uses the available setter method or
> retains the object by default if no setter method is available.
I admit that I didn't internalize this statement because the behavior
is different from the Mac. I also didn't internalize this because it
seems to contradict the standard Cocoa memory management rules. My
code doesn't retain the outlets so it shouldn't have to release them.
> If you define outlets for nib-file objects, you should also define a
> setter method for accessing that outlet.
Why SHOULD?
> Setter methods for outlets should
Why SHOULD?
> retain their values, and setter methods for outlets containing top-
> level objects must retain their values to prevent them from being
> deallocated. If you do not store the top-level objects in outlets,
> you must retain either the array returned by the |
> loadNibNamed:owner:options:| method or the objects inside the array
> to prevent those objects from being released prematurely.
In a nib loaded by UIViewController I have no access to the top level
objects array so this isn't usually relevant.
The shoulds in there confused me. The fact that the behavior is
different from the Mac confused me. The fact that the behavior seems
contrary to standard Cocoa memory management rules confused me. I
assure you that I'm not the only person confused by this and who
doesn't understand this. -
On Nov 18, 2008, at 1:14 AM, Brian Stern wrote:
>
> On Nov 18, 2008, at 12:59 AM, Roland King wrote:
>
>>
>>>>
>>>> Hey Brian -
>>>>
>>>> Outlets for iPhone OS are established by calling
>>>> setValue:forKeyPath:. The behavior of setValue:forKeyPath: is
>>>> that if a setter exists, it is called. If a setter does not
>>>> exist, the instance variable is looked up and set directly, and
>>>> if it is an object, it is retained. This means that for
>>>> IBOutlets, with no setters, they're retained in iPhone OS. This
>>>> is different from Mac OS X. If you're writing code on both
>>>> platforms, or are planning to, you should always use properties
>>>> on both platforms since it makes the decision to retain outlets
>>>> explicit and obvious.
>>>
>>>
>>> How come the documentation that mmalc quoted doesn't have this
>>> clear statement?
>>
>>
>> which one did he quote, the one I suggested to you has it .. it's
>> under Nib Object Retention. It's a page I have bookmarked because
>> as I switch between iPhone and regular OSX I like to remind myself
>> what it says. It's pasted below.
>
> Yes, that's it. I've read it plenty of times.
>
>
>>
>>
>> iPhone OS - managed memory model
>>
>> Objects in the nib file are created with a retain count of 1 and
>> then autoreleased. As it rebuilds the object hierarchy, however,
>> UIKit reestablishes connections between the objects using the |
>> setValue:forKey:| method, which uses the available setter method or
>> retains the object by default if no setter method is available.
>
> I admit that I didn't internalize this statement because the
> behavior is different from the Mac. I also didn't internalize this
> because it seems to contradict the standard Cocoa memory management
> rules. My code doesn't retain the outlets so it shouldn't have to
> release them.
>
>> If you define outlets for nib-file objects, you should also define
>> a setter method for accessing that outlet.
>
> Why SHOULD?
So that it's obvious to the reader of the code what is retained, and
what isn't. If you have setters then you can easily look at the .m
file and verify that the retains and releases are all balanced without
having to know anything else.
>> Setter methods for outlets should
>
> Why SHOULD?
You're free to have an outlet be non-retained, it's up to you. The
same rules should apply to outlets that apply to other instance
variables. You should retain your instance variables so they don't go
away when you don't expect them to. You just have to watch out for
creating cycles. If you do create a cycle, you can either break it
explicitly, or you can use some non-retained instance variables.
>
>
>> retain their values, and setter methods for outlets containing top-
>> level objects must retain their values to prevent them from being
>> deallocated. If you do not store the top-level objects in outlets,
>> you must retain either the array returned by the |
>> loadNibNamed:owner:options:| method or the objects inside the array
>> to prevent those objects from being released prematurely.
>
> In a nib loaded by UIViewController I have no access to the top
> level objects array so this isn't usually relevant.
>
> The shoulds in there confused me. The fact that the behavior is
> different from the Mac confused me. The fact that the behavior
> seems contrary to standard Cocoa memory management rules confused me.
Which parts do you feel are contrary? I'm guessing it's that outlets
with no setters are retained. If that's the case, you might consider
thinking of it this way: Interface Builder for the iPhone uses key
value coding. That's really the truth of the matter and accurately
describes everything that is going on. That outlets without a setter
are retained is a side effect of using key value coding. Additionally
having the outlet retain by default, and making that be the
recommendation when you use properties or setters comes into balance
with the fact you don't have to send a release massage to each top
level nib object after loading a NIB on the iPhone. With that, the
memory management rules for NIB loading on the iPhone actually pretty
concise:
1. Outlets are set with key value coding - implies outlets with no
setters are retained.
2. If you retain an outlet, you must release it.
3. If you want something to stay alive after the call to
loadNibNamed: you need to retain it in some way.
There really isn't anything in that list that is out of line with
Cocoa memory management patterns.
Also, just incase you aren't familiar with it, here's a link to the
key value coding programming guide: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/
Good Luck -
Jon Hess
> I assure you that I'm not the only person confused by this and who
> doesn't understand this.
-
On Nov 18, 2008, at 2:12 AM, Jonathan Hess wrote:
> Which parts do you feel are contrary? I'm guessing it's that outlets
> with no setters are retained.
Yes, that's the root of the whole issue. The fact is that outlets
without setters that are retained aren't released by the code that
retained them. The responsibility for releasing them is implicitly
passed on to some other code. I misunderstood this after reading that
paragraph a number of times because it is simply contrary to my
understanding of Cocoa memory management. I think it is contrary to
the Cocoa memory management rules that the code that retains these
objects isn't releasing them.
Now that I know that, there are still problems. The outlets can be
released in more than one place. As mmalc mentioned, the view
controller's view may be unloaded in response to a memory warning.
However, the view won't be unloaded if the view controller is the
frontmost view controller. There's no simple way for a view
controller subclass to know if it's the frontmost view controller or
therefore if its view will be unloaded. There is no viewDidUnload
callback that would be the right place to release the outlets in this
case. The code that mmalc showed is not correct because it doesn't
take into account the fact that the frontmost view controller won't
unload its view.
In effect it is the UIViewController base class that is retaining the
outlets, or causing them to be retained, when the nib is loaded. But
it abdicates responsibility for them. The UIViewController base class
is also the class that is releasing its view without any notification
to the derived class that it should also release the outlets.
I haven't decided how I'm going to fix all this. Either I'll add
assign properties so the outlets are not retained or I'll release them
all in viewDidLoad.
Most nib-loading on iPhone OS is done by UIViewController and I
suppose most of my complaints above are with the UIViewController
implementation. In my code I would hardly ever have a reason to want
to retain an outlet. Having outlets be retained by default gives my
code no benefit, and causes some complications.
--
Brian Stern
<brians99...> -
On Nov 17, 2008, at 9:33 PM, Jeff Laing wrote:
> How about:No, it's because it hasn't been updated.
> http://developer.apple.com/samplecode/CacheInfo-MacOSX/listing1.html
> (for example) which has the IBOutlet tag on the instance variables
> rather than the properties; I'll bet its different because properties
> and instance vars have the same name, isn't it?
>
> That example declares dozens of IBOutlet's, whose properties areThat's a bug (filed).
> (nonatomic,retain) and doesn't release any of them in its dealloc.
>
mmalc



