Can you help me understand retain counts in cocoa/objective-c? - iphone

> .h file:
NSString *myString;
#property (nonatomic, retain) NSString *myString;
> .m file:
self.myString = [[NSString alloc] init];
If i'm not wrong i will end up with an NSString instance with retain count of +2. Right?
I'm curious because Apple's example for Location uses "self." for initialization. Why? I checked and it does show retain count to be +2.

To answer your first question:
Yes, the retain count would be two.
To answer your second question:
The reason for using:
self.myString = x;
which is equivalent to:
[self setMyString:x];
is so that all of the property handling code is properly executed. This includes KVO notifications, and the code that automatically retains x as it is passed in.
If you were to simply set:
myString = x;
in the .m file, you would bypass all of that hidden property setting code, and simply set the myString member variable to a pointer to x.

Mustafa: Yes, you're correct. (The property should be declared as copy, not retain, but that's another matter.)

In your Modification 1, you're setting your instance variable directly to an autoreleased object. This means that at the end of the event loop your locationManager will be released and in this case, you'll then have a reference to a now unused block of memory.
Your Modification 2 looks correct to me, as does the sample code you've started from.

Related

Send parameters between view controllers

Before Xcode 5, I use for send parameters between viewcontrollers in the .h file
NSString *test;
#property (nonatomic, strong) NSString *test;
and in the .m use
#synthesize test;
and in the first view controller use:
SecondViewController *testC = [[SecondViewController alloc] init];
testC.test = #"Something ...!";
but it always show null in the debugger what is the problem or is there another way ?
Two suggestions:
Do not explicitly declare instance variables (ivars) to back up your properties. When the property is synthesized, it automatically creates ivar for you. If you create ivar manually, like above, you only introduce an opportunity to end up with typo resulting in two ivars, one of which will be nil. There is no benefit to explicitly declaring your instances variable anymore, and only can introduce problems.
I wouldn't even advise having your own #synthesize line anymore. The compiler does this for you and it does something equivalent to #synthesize test = _test. This is following best practice that your instance variable should have a leading underscore in its name, minimizing the chance of accidental use of ivar when you intended property.
In terms of what's going on, it could be many things, but it's hard to tell without seeing more complete code sample, but I suspect some problem with your manually defined instance variable.

iphone - properties and instance variables

Suppose I have this code...
foo.h
#interface Foo : NSObject {
NSString *aString; // 1
}
#property (nonatomic, retain) NSString *aString;
foo.m
#synthesize aString = _aString;
....
- (void)dealloc {
[aString release];
[super dealloc];
}
My questions are:
do I really need to declare aString in "1"? (see code)
if I am synthesizing aString = _aString, I am already creating an instance
variable, right?
if I am retaining the property on foo.h (#property), why Xcode complains if I release aString in dealloc?
thanks.
You are mixing up the property and the backing variable. "aString" is the property, which you access via method call (e.g. [self aString]). "_aString" is the backing variable, which you access directly (e.g. _aString).
Taking your questions in order:
No. This is an unused variable because you told the compiler to use _aString as the variable. (You don't actually need to declare either one in the modern run-time.)
Yes, as indicated in my answer to the first question.
Because the compiler expects you to send a message to an object, and "aString" is undefined as written. Normally you would use [self aString] to access the object, but this is a special case: in -dealloc and in -initXYZ you don't use accessor methods because of potential side effects. Switch to [_aString release] and everything will work (unless you have ARC, in which case you don't release at all.
With your #synthesize, the instance variable (your "1") should be NSString* _aString.
The reason you use synthesize with a differently named variable is so that you always use self.aString to properly release the old object instead of accidentally overwriting the pointer by directly modifying aString.
Do you have ARC enabled? If so, that's why Xcode complains about releasing it.
To answer your questions in order:
No. There might some sort of "best-practice" reason that I'm missing, but #property will synthesize the instance variable as well.
When you declare aString = _aString, what that allows you to do is directly manipulate _aString without accessing the synthesized getter/setter (by calling _aString) or use the synthesized getter/setters (by calling self.aString).
You are likely releasing it somewhere else, someone else is over-releasing it, or you're using ARC. With NSStrings (and other simple objects that have deep copy method readily available), I find it best to use #property (copy), and _aString = [stringPassedToInit copy], so that you are the only one handling your string's retain count. If you're using ARC, you don't need to worry about retain/release in most instances.
No, you don't need to declare ivars any more (since iOS 3 I think). You can delete the entire { ... } part of your interface declaration and it won't make any difference.
It's complaining because your ivar is named _aString, not aString. You need to say
[_aString release]
instead.
Answers : -
do I really need to declare aString in "1"? (see code) - Now with iOS 4 onwards you won't need to declare.
if I am synthesizing aString = _aString, I am already creating an instance variable, right? - Yes
if I am retaining the property on foo.h (#property), why Xcode complains if I release aString in dealloc? - now you need to use this - self.aString = nil, this will take care.
My answers are:
NO
YES
Try [_string release] instead.

get the value of a NSString variable

I have a weird problem.
pictureLink is a global variable declared in .h
NSString *pictureLink;
}
#property(retain,nonatomic) NSString *pictureLink;
i wrote this code
NSString * myPictureUrl=[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash];
pictureLink=myPictureUrl;
I have a strange result, it must be a pointer
Or
pictureLink=[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash];
i have EXC_BAD_ACESS error
It's memory management fault, you're not retaining myPictureUrl in your code.
[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash]; returns an autoreleased value, so you have two options:
pictureLink=myPictureUrl; should look like [self setPictureLink:myPictureUrl];.
do a [myPictureUrl retain];, and don't forget to release it later.
Consider using ARC (Automatic Retain Counting) for you project. With ARC the compiler takes care of retain counts so you don't have to, in fact aren't allowed to. There is a refactoring that will convert a current project.
You are bypassing your #property by calling directly the variable, so no magic provided by your #property settings is done, like retain and release.
you need to do self.pictureLink to use the #property.
To avoid the temptation of accessing directly my variable I do the following
NSString *theProperty
}
#property (nonatomic, retain) NSString *property;
and
#synthesise property = theProperty;
That way if I go around the #property I really, really wanted to do it.
But you need a very, very, very good reason to do so, and event then, it may not be a good enough reason.

Do I use retain or copy in my singleton?

I read somewhere that with NSString in an object, one has to use copy instead of retain. Can someone explain if this is correct and why?
For example I have the following declaration for my singleton:
#import <foundation/Foundation.h>
#class FaxRecipient;
#interface MyManager : NSObject {
NSString *subject;
NSString *reference;
NSString *coverSheet;
FaxRecipient *faxRecipient;
}
#property (nonatomic, retain) NSString *test1;
#property (nonatomic, retain) NSString *test2;
#property (nonatomic, retain) NSString *test3;
#property (nonatomic,retain) FaxRecipient *faxRecipient;
+ (id)sharedManager;
#end
I think "has to" in the sense of must is a little strong. You can use either copy or retain, but you should generally use copy for your NSString* properties because:
You usually don't want a string property to change under your nose;
NSMutableString is a subclass of NSString, so it's entirely possible that someone might set your NSString* property to point to a mutable string, thus creating the potential for the string to be changed while you're using it;
For immutable classes like NSString, copy operations end up just retaining the original object anyway.
Considering those three points, it's hard to think of a good reason to use retain instead of copy for your NSString properties.
prefer copy. it does not matter whether your class is or is not a singleton.
i wrote a fairly lengthy explanation for this, which details mutable and immutable types here:
NSMutableString as retain/copy
You can also use copy instead of retain. I use copy for NSString. There is good discussion on this topic. Here is a stackoverflow post NSString Copy or Retain?
You could use either,In both cases you will be owner of the objects and need to be released in dealloc.
Difference between copy and retain .
retain :--> It just increase the retain count on the exist object.
copy :--> it crate the new object for your property
In both cases: you will have the ownership of objects.
Read Apple memory management concept.
# Claus Broch: From Apple Documentation
You take ownership of an object if you
create it using a method whose name
begins with “alloc”, “new”, “copy”, or
“mutableCopy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message.
You should use the retain value in this instance. The reason for this is that
1. you don't want the object to be deallocated
2. you are most likely going to want to change the value of the NSString at some point
Using the copy attribute is basically saying that the value of your NSString should not change without warning. i.e. it will stop the value of the NSString being set and retrieved at the same time.
For this implementation, you should use retain, or at least thats my understanding. For more look here: http://cocoawithlove.com/2010/06/assign-retain-copy-pitfalls-in-obj-c.html

Releasing an ivar with the Copy property

If I have a class
#interface Foo {
NSString *temp;
}
#property(nonatomic, copy) NSString *temp;
#end
I understand that upon assignment, the old temp will get released and the new one will be assigned using temp = [newTemp copy]. And going by memory management rules, you are supposed to do [temp release] in the dealloc method of Foo, right?
What I don't understand is what happens if the setter was never used - you still have the [temp release] in the dealloc, so it's releasing something with a retain count of 0. Can someone clarify this for me?
There are two possibilities.
Since you never set it, it's nil. Sending release to nil is just fine. So no problem there.
Your init routine makes a default value for temp. Then it is a real object, and sending it release is also ok.
No problem all around! In neither case are you sending a message to an object with a retain count of 0.