Why can I not initialise my variable without using self - iphone

I have the following variable defined:
#property (nonatomic, retain) NSMutableArray *arraySpeechSentences;
And I am trying to initialise it in the following way:
// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;
[speechSentences release];
When I try to call [arraySpeechSentences count] the application crashes. However, if I set the variable in the following way:
// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
self.arraySpeechSentences = speechSentences;
[speechSentences release];
I can call [arraySpeechSentences count] perfectly fine. I was under the impression that if you use self. it simply checks to see if variable is already set, and if so it will release the object before assigning it the new value. Have I got this wrong, and if so when should I be using self. to set values?
Thanks for any help,
Elliott

Using a setter (like self.foo = ... or [self setFoo:...]) does release the old value but it also retains the new value, which is needed in the example you give.
The issue is that you're alloc and init'ing your array, and then releasing it. This indicates you no longer need it. So, you should either use the setter (usually preferable) or don't release your array.

If you're not using ARC, you should type
arraySpeechSentences = [speechSentences retain];
because you're accessing the instance variable directly, which means the value of the instance variable arraySpeechSentences will be the address of the speechSentence object, which you just released, so which is an invalid pointer. The semantic you declared in the property doesn't have an effect on the instance variable itself.
When you type self.arraySpeechSentences, you're actually using a shortcut for the setter [self setArraySpeechSentences:speechSentences], which actually retains the value passed as parameter (if you synthesized the property, it is retained because you specified retain in the property declaration; if you wrote the accessor yourself, it is your job to ensure you retained the value).

I'll try to give a detail answer for this.
First when you use #property/#synthesize directive you create getter and setter methods around a variable.
In your case, the variable is called arraySpeechSentences (the compiler will create the variable for you) and you can access these methods (setters and getters) with self..
self.arraySpeechSentences = // something
is the same as
[self setArraySpeechSentences:something]; // setter
And
NSMutableArray* something = self.arraySpeechSentences;
is equal to
NSMutableArray* something = [self arraySpeechSentences]; // getter
In the first snippet of code
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;
arraySpeechSentences points to the same object speechSentences points to. But when you do [speechSentences release] you dealloc that object and now arraySpeechSentences is a dangling pointer. You receive a message sent to a deallocated instance I suppose. Try to enable Zombie to see it.
Speaking in terms of retain count, the array has a retain count of 1 when you do alloc-init.
But when you release it, the retain count goes to zero, the object doesn't exist anymore and you have a crash when you try to access arraySpeechSentences.
Instead, when you deal with properties, the policy applied to a variable is important. Since the property use a retain policy, when you set an object
self.arraySpeechSentences = // something
the retain count for the referenced object is increased. Under the hood, saying self.arraySpeechSentences = // something is equal to call the setter like
- (void)setArraySpeechSentences:(NSMutableArray*)newValue
{
// pseudo code here...
if(newValue != arraySpeechSentences) {
[arraySpeechSentences release];
arraySpeechSentences = [newValue retain];
}
}
The second snippet work since the retain count for your object is one when you do alloc-init, becomes two when you call self.arraySpeechSentences = and returns to one when you do the release. This time, the object is maintained alive since it has a retain count of 1.
If you have a property with a retain or copy policy, don't forget to release the object in dealloc like, otherwise you can have leaks.
- (void)dealloc
{
[arraySpeechSentences release];
[super dealloc];
}
To understand how Memory works I suggest to read MemoryManagement Apple doc.
P.S. Starting from iOS 5 there is a new compiler feature, called ARC (Automatic Reference Counting), that allows you to forget about retain/release calls. In addition, since it forces you to think in terms of object graphs, I suggest you to take a look into.
Hope that helps.

Related

Allocating a property

Working on someone else's code. Came across a piece of code while analyzing the project
self.groupPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0,260,320,216)];
self.groupPicker.delegate = self;
self.groupPicker.showsSelectionIndicator = YES;
[self.view addSubview:self.groupPicker];
Where groupPicker is a UIPicker property. When analyzing the project I encountered a potential leak warning in this case. I have also noticed that the groupPicker property is not being released in the dealloc method. Nor is _groupPicker released anywhere in the project. What should be done in this case?
Should I remove the UIPicker property and just declare a UIPicker variable instead.
Should I just release groupPicker like [_groupPicker release];
What would be the retain count of groupPicker as it is retained once in the .h file and again being allocated as shown in the above piece of code.
1) No, it is perfectly fine to have the property, the problem is that it is being over retained. When you alloc/init the retain count is 1, then you use the retained property which increases the retain count again. The retain count is now 2 and assuming you release the object in dealloc, you end up with a retain count of 1, i.e. a leaked object.
There are many ways you can handle the problem. I think the best way is to autorelease the object on initialization. Like so
self.groupPicker = [[[UIPickerView alloc] initWithFrame:CGRectMake(0,260,320,216)] autorelease];
2) Anything you retain should be released in dealloc, so in dealloc you should
- (void)dealloc {
[_groupPicker release];
[super dealloc];
}
Watch out! When you set a property like
self.property1 = x;
and the property1 is declared as retain, the previous object in the property1 is released and the new object (x) is retained. This is why doing this:
self.property1 = [[x alloc] init];
when property1 is declared as retain, will retain x twice. (one for init, one for setting the property)
The correct way is declaring the object, setting to the property and then releasing
object x = [[class alloc] init];
self.property1 = x;
[x release];
This way, you give the "responsability" of releasing the object x to the property holder.
While using ARC for iOS5+ applications should be preferred, if you don't want to do that just use autorelease after init method.
You should use ARC (Automatic Reference Counting)
to do so got to edit>refactor>convert to objective c ARC
Either assign the UIPickerView to _groupPicker (or whatever the instance variable is named), or use an autorelease on the value as you assign it.
(The problem is that assigning to a retained property causes a retain, and there's already a retain on the object from the alloc.)

property assign

If I have one property like this, what is the diference of assign the value of the property of the first mode and the second mode?
#interface Prueba : NSObject{
CustomeClass *_cclass;
}
#property(nonatomic, retain)CustomeClass *cclass;
#end
#implementation Prueba
#synthesize cclass = _cclass
- (void)config{
// 1 This
self.cclass = [[CustomeClass alloc] init];
// 2 This or
CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
}
#end
:/
Your first example gives you an object with a retain count of two (wrong), whereas your second example gives you an object with retain count of one (right). The second method is preferred in non-ARC projects. Alternatively, you could also do either set the ivar yourself (which I don't like because you're not using the setter):
_cclass = [[CustomeClass alloc] init];
or use the setter as your examples do, but do an autorelease (which I don't like because you shouldn't defer your releases unless you have to):
self.cclass = [[[CustomeClass alloc] init] autorelease];
In your non-ARC project, your original second example is best (using a pointer, using your property's setter, then releasing your pointer), because for KVO you want to get in the habit of using the setter:
CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
There is no difference in the result except that in the second method you create an additional pointer. In both versions self.cclass will hold your object just fine.
The problem is that when you only release the object in your second mode, in the first mode you'll have a memory leak. Since the retainCount of an object is +1 when you allocate it, you assign a +1 object through your setter. This means, that you actually bump up the retainCount again. Now if you don't release the object after assigning it to your property, once it gets released from there the retainCount will only be reduced by 1. Thus letting an object with a retainCount of +1 float around in the memory, lost forever.
But because you are already asking about a better version, I want to introduce lazy instantiation to you. What you can do, is that you overwrite the getter method of the property in question and check if it has been allocated yet. If not, you allocate it inside your getter method and then return it. It would look something like this:
- (CustomeClass*) cclass
{
if(!_cclass)
{
_cclass = [[CustomeClass alloc] init];
}
return _cclass;
}
With this method you assign a +1 retained object to an internal variable, thus bypassing the setter and not increasing the retainCount. Also it's memory friendly, because you object only gets instantiated when you really need it. Now when you set your property to nil or some new object, the old object will be properly deallocated.
EDIT:
In response to Robert Ryan's comment I want to add the following:
This does not break KVO, or interfere with the assigned qualifies for your properties. If your property is marked as assign or weak, then lazy instantiation doesn't really make sense. If it's marked as retain or strong this way of instantiating an object is perfectly fine, especially when it is a property which you would assign anyway inside a config method.
Regarding KVO: the value which is assigned inside the getter can be seen as the initial/default value, so KVO still works. It will trigger when you use the setter to assign something else to the property. You wouldn't want KVO to trigger because of a default value, would you?

iPhone alloc and release

i am new in ObjC and iPhone.
I downloaded an example of data sharing between multiple views. The basic approach is to create an data model object in the base UIApplication and get/set data from/to it. So in the init method i saw the following code:
- (id) init;
{
self.theAppDataObject = [[ExampleAppDataObject alloc] init];
[theAppDataObject release];
return [super init];
}
And after that, using delegate we can access this object.
id theDelegate = (id) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
So, my question is in the first code example. Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object? Why don't we get nil when accessing this object later?
10x
I assume theAppDataObject is declared as #property (retain). Therefore, when setting the object by doing self.theAppDataObject (or [self setTheAppDataObject:]), this property will retain the ExampleAppDataObject. Therefore, you can release it afterwards.
When you alloc and init the ExampleAppDataObject, it's retain count goes up to 1. When you set the AppDataObject to this ExampleAppDataObject, it sends retain to it, so the retain count goes up to 2. You can then release your own ownership of the object; it won't get deallocated because theAppDataObject still has ownership.
If that makes sense.
That depends on how theAppDataObject property is defined.
If it provides a retaining setter-accessor the retain count of the appDataObject will flip to 2, one more than needed here.
So release one of it.
Better and more understandable way would be to write
if ( (self = [super init]) ) {
ExampleAppDataObject *myAppDataObject = [[ExampleAppDataObject alloc] init];
self.theAppDataObject = myAppDataObject;
[myAppDataObject release];
}
return self;
Iphone uses reference count based memory management model..See this tutorial first and then apple's technical documentation... theAppDataObject is a property (see the use of self. theAppDataObject) which should be retained for the above code to work..Any object which is retained should have a bonus plus 1 retain count...An object only gets released when its retain count gets to zero..
first things first: that code sample is terrible.
- (id) init
{
// assign self. super may return another address
self = [super init];
// then check for nil
if (self != nil) {
// then assign the ivar directly because you should
// not invoke methods of partially constructed objects
theAppDataObject = [[ExampleAppDataObject alloc] init];
}
// then return the address super returned
return self;
}
now for your questions:
Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object?
self.theAppDataObject calls through the setter, which retains, copies, or assigns theAppDataObject. in this case, we could assume it is highly likely to be retained.
Why don't we get nil when accessing this object later?
release does not set a pointer to nil. it sends a message to the object which then decrements the retain count (in the typical case). what you might have expected in this case is an object which has been deallocated. that does not happen when the argument is retained because the reference count does not reach zero in the program you have shown. the object is still alive because it's been retained and the address of the object stored when the setter (self.theAppDataObject = arg) is called.

assignment of property and allocation leads to retain count of 2

I had a look at instruments and I saw that the alloc increased the retain count by 1. So far everything clear. But the assignment of the class to my property also increased the retain count to 2.
self.myProperty = [[MyClass alloc] init]
Vs.
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable
To decrease the retain count to zero I released myCreatedVariable right after my calls. The myProperty instance variable is released in the dealloc method. Am I right that a property only is released in the dealloc method?
Now to my question:
Is the allocation and the assignment to a property always creating a retain count of 2? So don't use
self.myProperty = [[MyClass alloc] init]
because the retain count is never getting zero? Or is this only the case if I'm allocating a class?
Cheers
Your property is most probably declared as retaining or copying:
#property (retain) MyClass myProperty;
or
#property (copy) MyClass myProperty;
This calls your setter that does what its attributes say: retain! Copy will also retain.
Although it worked here, you shouldn't try to get useful information out of the retainCount property.
I cannot recommend the Memory Management Programming Guide highly enough, well worth a first, second and third read. :-)
Creating objects using the init function returns a retained instance by default. ( See the Memory Management Programming Guide)
If the property is defined with the 'retain' attribute, then your object is retained one more time.
So the right way to do is
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable;
[myCreatedVariable release];
By the way this is good to know also when you using Arrays.
Once an object created with the alloc and init functions is added into an array, it is retained by the array, so you can release your instance after you add it in the array.
In both case, retainCount is then 1, as expected.
if your property is defined with the 'copy' attribute, you can release the object as well, and even kill it, since it has been fully copied and retained once.
( I think there is something there if you use garbage collection instead of managed memory... To check.. )
Finally if your property is set with the 'assign' attribute, only the object's adress is copied, so you should not release your original object in this case.
It is however not recommanded to use the 'assign' attribute, since you may set property with objects that you did not create yourself, and which could be released anytime, letting your property pointing in the fields...
Finally, don't forget that static creators in Cocoa do not return retained objects.
( This is a convention, exceptions may exist... )
example:
NSArray* myArray = [NSArray array];
self.myProperty = myArray;
In this case, do not release myArray, it is already done in the creator function.
Assigning it to the property will retain it.( with retain or copy attribute).
Hope it will help,
Cheers
#property (nonatomic, retain) NSString *strURL;
This will keep the Retain count = 0
When you use an accessor to initialize the strURL then the retain count increases to 1
self.strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
However if you had done this without using the accessor then your reference count would have remain same that is 0
strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
Note that when you use this variable with retain count as 0, the auto release works and the variable gets released, giving "SIGABART" error or “EXC_BAD_ACCESS” when you try to access its value.
Generally when you are using init to get your variables initialized the best practice is to use alloc.
strURL = [[NSString alloc] stringWithString:#"http://192.168.1.25/shop.php"];
Hope this helps!
Sorry ? Noooo. I'm afraid programming is trying to know things we don't know everyday !
Static creators are convenience function, to ease common objects allocations.
A lot of classes in the cocoa framework have this kind of functions. Arrays, Dictionary, Paths, ...
Let's take your class as an example, and suppose you often have to create objects of this class. You may write a function in your 'myClass' implementation like:
+(MyClass*)myClass
{
MyClass *myNewInstance = [[myNewInstance alloc] init];
return [myNewInstance autorelease];
}
Then you can rewrite your original example as:
..
self.myProperty = [MyClass myClass];
..
Straight!
Or you could write a method like
-(void)myFunction
{
MyClass* myTempObject = [MyClass myClass];
if (myTempObject) {
// do something with your temporary object
}
// Simply exit, object will be released later on.
}
It is much shorter ( we should handle the case where object creation failed ) ..
Note that this is all conventions, you can basically do has you like and create retained objects, or use a different name for the creator.
But it is safer to follow the framework rule, it then becomes a reflex when you code.
See methods like [NSDictionary dictionary], [NSArray array], [NSArray arrayWithObjects:] ,...
Cheers

Objective-C Setter Memory Management

Still a little confused about Objective-C memory management. I think my confusion stems from what exactly the autorelease means.
NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];
Now, what should I do with the accountDictionary in the setAccountDictionary method of my view controller? Right now I just set the instance variable "accountDictionary" to whatever is returned. Should I set it to a retained one, and then release the one that's returned? What should my setter code block look like, given that NSString's propertyList method is autoreleased?
By the way, if I release theBackendResponse, will I lose the accountDictionary? I assume not...
Calling [objectInstance autorelease] adds an object to the current NSAutoreleasePool. When that pool receives a drain message, it sends a release to all the objects in the pool. If any of those objects' retainCount reaches 0, they are deallocated at that point. The purpose of autorelease is to allow you to mark an object to be released "some time in the future". This is especially useful for things like methods that return a newly allocated object but want to release it so that the caller doesn't have to take ownership of the returned object. A method might look like this:
- (id)myMethod {
id myObj = [[SomeClass alloc] init];
...
return [myObj autorelease];
}
The caller of myMethod would then retain the return value if they wanted to take ownership of the returned value or ignore it if not. When the current NSAutoreleasePool is drained, myObj will get a release message. If no other objects own it (i.e. have sent it a retain message), it will get deallocated.
All of this is explained in the Cocoa Memory Management Programming Guide. Even if you've already read it, it's always worth an other read.
So, to answer your questions:
First, you should release theBackendResponse. You will leak memory if you do not. You don't need to know what accountDictionary does with the string: if it needs to keep a reference it will have retained theBackendResponse. You have an ownership of theBackendResponse because you alloc'd it, so you must relinquish that ownership (via release or indirectly via autorelease).
Second, you must retain or copy the argument to setAccountDictionary: if you want to keep a reference to that object or value respectively. The standard setter method looks something like this (assuming you do not need atomic semantics):
-(void)setAccountDictionary:(NSDictionary*)newDict {
if(newDict != accountDictionary) {
id tmp = accountDictionary;
accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
[tmp release];
}
}
You must also remember to release accountDictionary in the dealloc method:
- (void)dealloc {
[accountDictionary release];
[super dealloc];
}
Since you appear to be using NSViewController, I assume you're on Leopard (OS X 10.5) in which case, you should probably be using #property and the #synthesized getter/setter if possible. To do this, add a
#property (copy,readwrite) NSDictionary * accountDictionary;
declaration to the class #interface. And add a #synthesize accountDictionary; directive in the #implementation block for your controller class.
In general, one object or method should not have to care about how another is managing memory. The fact that somebody else has autoreleased something is irrelevant to you. It's simpler to think of the concept of ownership. So retain and some other methods claim ownership, and release and autorelease relinquish it. If an object needs to keep a reference to another, it should claim ownership for as long as it needs. Thus, setter methods usually either retain or copy the new value and release or autorelease the old value.
I strongly recommend reading the Cocoa memory management guidelines. They're not all that long or complicated, and it's very important to understand them.
The set accessor method should always copy / retain the incoming value before releasing the old, in the case where the old value is the only object that owns the new value:
-(void)setAccountDictionary:(NSDictionary*)newDict {
id old = accountDictionary;
accountDictionary = [newDict copy];
[old release];
}
If accountDictionary referred to newDict and the retain count for newDict was 1, the call to [accountDictionary release] before the call to [newDict copy] would cause the retain count to got to 0 and therefore release newDict.
As an example of incorrect code, where we release the old dictionary and then copy the new dictionary:
-(void)setAccountDictionary:(NSDictionary*)newDict {
[accountDictionary release];
accountDictionary = [newDict copy];
}
and have the following code:
NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];
It's contrived, but it demonstrates that in the setter, accountDictionary and newDict refer to the same instance. If the retain count is 1, the [accountDictionary release] line will decrease the retain count to 0, and thus release the instance from memory. [newDict copy] will now refer to an invalid instance.
Apple describes several concepts when implementing accessors: Memory Management Accessor Methods
If you can use Objective-C 2.0, I would go with properties and dot syntax.
Properties are new in Objective-C 2.0 and provide auto accessor generation.
In the .h File:
#property (retain) NSDictionary* accountDictionary;
In the implementation:
#synthesize accountDictionary;
Synthesize generates accessor methods for your NSDictionary. (If you want to provide your own implementation, you could also do that)