Say i create a Person class and within a different class header file i
create a person instance as follows:
Person *barry;
@property (nonatomic, retain) Person *barry;
now within the implementation files init method, i have noticed the
following being done to instantiate the instance:
Person* p = [[Person alloc]init];
self.barry = p;
[p release];
and in dealloc method a release being called.. Now My question is can
i not simply do the following in my init method instead?
barry = [[Person alloc]init];
why is instance created.. assigned to "barry" then released?
Many Thanks
By
Vicki
1. when you do...
@property (nonatomic, retain) Person *barry;
you 'retain' so you must release, thus in your implementation's
dealloc you balance this out:
- (void) dealloc {
[barry release];
[super dealloc];
}
2. if you do...
barry = [[Person alloc] init];
...you used alloc, so aside from the [barry release]; at your dealloc,
you need another [barry release]; but what if you need to use barry in
your code, when will you add the [barry release]? So, if you used...
Person* p = [[Person alloc]init];
self.barry = p;
[p release];
...you don't have to worry about doing a [barry release]; since you
did not alloc or retain another instance of barry. All you did was
alloc 'p' which you have now released and thus don't have to worry
about.
Although the only thing i can find on the default for properties
"assign" is that that it is a simple assignment and that it is
typically used for scalar types.
So an int or float can simply be assigned? but if i was to use assign
for a class instance would this not be the "best" way to manage
memory?
i shall give an example:
@interface College: NSObject {
int students;
NSString *collegeName;
Person *barry;
Person *sally;
}
@property (assign)int students;
@property (assign)NSString *collegeName;
@property (nonatomic, retain)Person *barry;
@property (nonatomic, retain)Person *sally;
@implementation College {
-(id)init {
if (self = [super init]) {
self.students = 187;
self.collegeName = [NSString
stringWithFormat:@"barrySixthForm"];
Person *p = [[Person alloc]init];
self.barry = p;
[p release];
self.sally = [Person init];
}
return self;
}
-(void)dealloc {
[students release];
[collegeName release];
[barry release];
[sally release];
[super dealloc];
}
}
is this correct? can i still use assign collegeName or should i use
retain? and when i set sally in the init method i dont use alloc so
the retain count stays at one and is set to 0 when i release in the
dealloc method.
Any feedback would be great
Thanks again
Byron
for C types like int, float, char, etc. use "assign"
for Objects that don't need setters/getters, use "readonly"
for NSString, you can use "copy"
for all the rest, use "retain"
"nonatomic" is used when you're not using threading (which as
beginning developers we rarely if ever use) in your iPhone app--to
speed up processing.
Regarding your query on using assign / retain / copy for properties...
The very helpful list given by bluelobe tells you when you should
typically use them although you may still be confused as to WHY you
should not use assign for object properties.
This relates to some fundamental programming concepts of primitive and
pointer data types. Someone else would probably be able to explain
this better but I'll have a stab at it.
Basically, if you think of a variable as an address in memory, then
for primitive types the content of that address is the actual value,
whereas for pointer types the content of that address points to
another chunk of memory containing the object data. This means that if
you make an assigment between two primitive types the actual value is
copied from one variable (address) to the other. If you make an
assignment between two pointer types only the object's address is
copied from one variable to the other, both variables are then
pointing to the same object data. If one of those variables then
releases that object and the other has not retained it the object will
be destroyed. As the properties of a class effectively represent its
internal state, it is very important that they don't get destroyed
until the class no longer needs them. Therefore all properties which
are pointers must either be copied (so the class owns them) or
retained (so they will not be destroyed until the class releases
them).
Hope that makes some sort of sense.
Vicki
ivarName = nil;
Thanks again for your time
Byron
I am maybe not the most qualified to answer .. but I will try my
0.02€ ;)
Even if you do not have to release something, it is good practice to
set the pointer back to nil once you finish using it.
This way if you place a call later (which is an error BTW) due to the
graceful fail of sending a message to nil in Objective-C, nothing will
happen.
Moreover when we will get GC on iPhones :) I guess that as you are not
pointing to this object anymore it will get deallocated.
I hope all the above are correct ;)
Enjoy Cocoa coding ;)
Best regards
Chewbee
> --
> You received this message because you are subscribed to the Google
> Groups "iPhone Application Development Auditors" group.
> To post to this group, send email to iphone-appd...@googlegroups.com
> .
> To unsubscribe from this group, send email to iphone-appdev-aud...@googlegroups.com
> .
> For more options, visit this group at http://groups.google.com/group/iphone-appdev-auditors?hl=en
> .
>
obj.ivar = nil;
The setter releases the current value of the ivar (equivalent to [ivar
release])
It sets the value to nil;
it does [ivar retain} on nil, which is OK...
I will attempt to answer your question. Before I do, please check out
the tools from the Run menu in Xcode, specifically the ones in Run
With Performance Tool, you will find an option called Leaks and one
called Object Allocator. If nothing else they have some nice
graphs :-)
Here is how I think of it:
An alloc = 1 on the retain count
A retain = +1 on the retain count.
A release = -1 on the retain count.
An assign = 0 on the retain count (i.e. no change)
So if you have the person Barry who you said should be retained as per
the property definition, we can walk through it as follows
Person *barry;
@property (nonatomic, retain) Person *barry;
Whoever barry is instantiated as it will automatically have a retain
count of +1. Since barry has not been instantiated at this point, you
*do not* have to release barry, i.e. you only have to if you choose to
instantiate an object and let barry point to it.
In your code you go ahead and instantiate an object and let barry
point to it:
Person* p = [[Person alloc]init];
self.barry = p;
[p release];
In the above code you alloc memory for Person p, let barry point to it
and release Person p. To walk through it p = a Person and because its
an alloc gets a retain count of 1. When you point barry to the same
Person, barry gets a retain count of 2, because you said barry should
retain whatever it points it (refer to the property def. of barry).
Then you said lets release the object that p points to which makes
it's retain count be 0 for pointer p and 1 for pointer barry.
At this point you must release barry at some point in your
application, typically done in the dealloc method, though you could
release barry at another part of the application (i.e. viewDidUnload)
and have it work fine.
As pointed out earlier the case with assign, is that if you set the
pointer to nil you *are* releasing the memory. An example:
Barry assigned to object X
(another pointer) Mannilow assigned to object X
you say you want Barry to point to nil, i.e. object X is now nil. Now
mannilow is also nil, and if you, like I seem to do way too often, try
to ask Mannilow something you crash :-)
I hope this helps, this is my understanding and it is entirely
possible I have it wrong, if so please tell me what I've missed.
Best,
Wayne
P.S. It was coincidence that in my first "real" job one of my
coworkers dubbed me "crash", he dubbed himself "burn" as the two of us
could take out a server in under 5 mins with our buggy code :-)
P.S.S. Thank you all for this group, without it I would have never
completed Paparazzi 2.
> >> For more options, visit this group athttp://groups.google.com/group/iphone-appdev-auditors?hl=en
As you should only be using assign with primitive data types, not only
do you not need to release them but you can't call release on them
because they're not (pointers to) objects.
I must admit, I can't see why anyone would do this in a dealloc method
rather than a direct release. I thinks its a mistake. It wouldn't
cause a problem - it would still work but I can't see the point. Once
you're in dealloc, your object is being destroyed so you may as well
release its properties directly without any additional performance
overhead.
However, there is a method in ViewController in which you are
*supposed* to take this approach.
If you create a new UIViewController subclass via file->new, you will
see this generated method:
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
As the view can be re-loaded, it is not sufficient just to call
release from this method, you need to assign to nil to ensure myOutlet
is not still pointing to some random bit of dealloc'd memory which
could cause problems when the view is re-loaded. If the value is set
to nil you can test it to determine if you need to initialise it. Note
- if myOutlet were not set up as a (retained) property it would not be
released and there would be a leak.
You could choose to use a similar approach where appropriate in order
to keep your memory usage down.
Vicki
byron
As I understand it, it is considered good practice to avoid using the
convenience methods in order to keep the application's memory usage
down.
When we use convenience methods the objects returned are auto-released
'later'. From what I can gather, this is at the end of the current
event loop. I guess this makes sense as otherwise something might get
released whilst we were still using it! This means if we use
convenience methods all the time and have lots of temporary data we
could use a fair bit of memory before anything gets released.
I think I read some guidelines about this somewhere but can't remember
where offhand. I'll have to go digging...
I guess for a very small, memory light app it may not matter? (unless
they start letting us multitask with other apps more than they do at
the moment...)
Vicki
Not wanting to belabor the point but, according to lecture 3 (Winter
2010 at around 48:00), using...
@property (nonatomic, retain) Person *barry;
...means the ff:
- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [newBarry retain];
// barry’s retain count has been bumped up by 1
}
}
while using...
@property (nonatomic, copy) Person *barry;
...means the ff:
- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [newBarry copy];
}
}
On the other hand, using...
@property (nonatomic, assign) means...
- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
barry = newBarry;
}
}
So, if Byron did this:
barry = [[Person alloc]init]; or more correctly...
self.barry = [[Person alloc] init];
...or in non-dot notation...
[self setBarry:[[Person alloc] init]];
...it would mean barry will get a retain count of 2: alloc + retain =
2 because:
- (void)setBarry:(Person *)newBarry {
if (barry != newBarry) {
[barry release];
barry = [ [[Person alloc] init] retain]; // alloc is 1, then retain
adds another 1
}
}
which means, Byron akwardly has to do a [barry relase] (aside from the
one in dealloc) to avoid memory leaks. To avoid this mess, one should
do the usual:
Person *p = [[Person alloc] init];
By the way, doing this...
barry = [[Person alloc]init];
...is not the same as doing this...
self.barry = [[Person alloc]init];
In the first example, you're assigning barry directly. In the second
example, you're calling "setBarry":
1) barry = [[Person alloc] init];
2) [self setBarry:[[Person alloc] init]];
...again from Lecture 3 around 52:00
in the .h file it literally has NSArray *array.. then when it is used
in the .m its something like this :
array = [NSArray arrayWithObjects:one,two,three,nil];
[self someMethodWithArray:array];
that is all.. what is happening here exactly?
Thanks in advance
Byron
> > iphone-appdev-aud...@googlegroups.com<iphone-appdev-auditors% 2Bunsu...@googlegroups.com>
Vicki