Difference between self.ivar and ivar? - iphone

aclass.h
#interface aClass : NSObject {
NSString *name;
}
#property (nonatomic, retain) IBOutlet NSString *name;
#end
aclass.m
#implementation aClass
#synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)test1 {
name = #"hello";
}
- (void)test2 {
self.name = #"hello";
}
Take above as an example. Could someone please explain the difference between name = #"hello" and self.name = #"hello"? Thanks!
EDIT: Follow-up question: How to write my own setter for an ivar, i.e.: self.ivar = ...?

BE AWARE, THIS POST IS OLD !
This post is from the previous decade.
Be sure to read the important footnote down below, cheers!!
It's really difficult to understand all this, when you're just getting started.
Here are some SIMPLE, PRACTICAL rules of thumb FOR BEGINNERS.
To repeat, this post is FOR BEGINNERS.
The aim here is to allow you to quickly move from the starting line, to being able to confidently use the system in most situations.
Later, you can really learn about the inner workings of these issues.
(1) Don't ever say name=#"hello". Always say self.name=#"hello". Do a project-wide search for name and ensure you always say self.name and not name, when you set it or change it.
(2) You know all that infuriating stuff about memory management, initialising, releasing and so on. If you use the self thingy, it takes care of all that for you. Cool huh?
(3) The self thingy is particularly useful because you can easily "change" the string (or whatever it is) as you go along. So, it's totally OK to do this,
self.name=#"aa";
self.name=#"bb";
self.name=#"cc";
whereas (in a word) you can never, ever, for any reason, do this...
name=#"aa";
name=#"bb";
name=#"cc";
( * ) Regarding your literal question, "please explain the difference between name = #"hello" and self.name = #"hello"?" This is easy to do.
The first one is just setting a variable. You know, exactly like "x=42" in the old days when life was simple and we were 13 years old.
The second one is completely different, specifically it is calling a complicated routine (known as "the setter") to do a whole lot of amazing and astonishing stuff for you.
So that is the literal answer to your question. The first one just sets the variable (and don't forget, there are a whole lot of pointers and other weird stuff involved, and as a rule you certainly can not just set pointers willy-nilly like that). The second one actually calls a big complicated routine and hence does a whole lot of stuff for you.
Once again, the second one is exactly like saying...
[name bigComplicatedRoutineHere:#"hello"];
...it is very helpful to always remember that the syntax self. ... is literally calling a routine.
Indeed, some thinkers on the topic thought it was a dumb idea when they introduced this self.X syntax to mean [X complicatedThingHere]. It introudces a lot of confusion, and every beginner asks exactly what you are asking.
Personally, it took me over nine years to get this clear in my head. :-) So again, I emphasise that you must remember that when you say self.x, in fact, you are actually calling a routine.
To repeat: the "self dot" syntax in fact calls a routine. (Indeed I believe one of the preprocessors simply expands it to [x amazingStuffHere]. )
I have tried to answer in a way that will keep you going and allow you to advance and use more features, while you learn about memory management, properties, and so on. If you are more advanced than this post, just ignore it.
Please note that this post is meant to be advice for beginners to enable them to keep going and not get infuriated. Hope it helps!
2014 update! Important Note on ARC for beginners ...
Note, this post is five years old now! It's been read by thousands of beginners and there have been many followup questions etc. Please note that, today in the new "ARC world". To some extent: if you're a beginner: you should pretty much only use!! properties. ie, use "self.whatever" at all times, everywhere. In any event, just be aware that the information in this post is "largely historic" and is becoming more so every day. Of course, it goes without saying that once you are an expert, you will need to and will understand every subtle detail of all this. Hope it helps someone.

self.name uses the accessor and/or mutator defined by you (this is nonatomic and retain in your case). So when you call self.name = foo, it will call the setName:(NSString *)str mutator generated by the compiler, which will first release the current string, then retains the new string and finally sets name to the retained string.
Just calling name = foo does nothing more than assigning name to foo.
This also means that you can only call self.xxx when you have defined a property for the ivar, otherwise the compiler will tell you that it doesn't know about it(iVar).

name = #"Joe"
You're accessing directly the variable, bypassing the getter method that Cocoa took the trouble of creating for you. Usually, not the wisest thing to do.
self.name = #"Joe"
Now your going through the method you asked cocoa to create for you. This is usually the best way.
As a rule of thumb, use always the setter and getter provided by Cocoa, with ONE exception: dealloc. In dealloc, you should always release the variable directly, not through the getter method:
-(void) dealloc {
[name release]; // instead of [[self name] release]
...
[super dealloc];
}
The reason to avoid accessors in dealloc is that if there are observers or an override in a subclass that triggers behavior, it'll be triggered from dealloc which is pretty much never what you want (because the state of the object will be inconsistent).
OTOH, there's also a slightly more convenient syntax for declaring iVars that you might not be aware of. If you are only targeting 64bit macs, You can use properties to generate both accessor methods and the instance variable itself:
#import <Cocoa/Cocoa.h>
#interface Photo : NSObject
#property (retain) NSString* caption;
#property (retain) NSString* photographer;
#end

It's real a memory management, firt the property grammar is real setter and getter method, when use self.xxx = ?, it could call setter method, the object retain cout +1, name can not be release, however if name = foo is nothing about property grammar.
setter method example:
-(void)setObj:(ClassX*) value
{
if (obj != value)
{
[obj release];
obj = [value retain];
}
}

Related

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.

Preferred way to name instance variable in Objective C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When do you make an underscore in front of an instance variable?
As in Objective C, instance variable are protected by default, what are your preferred way to name it?
Assume you have an variable name, the following 3 ways have their supporters.
_foo
foo_
foo
foo. I have always disdained the _foo or foo_ styles.
Apple's Coding Guidelines for Cocoa suggest you avoid an underscore prefix:
Avoid the use of the underscore
character as a prefix meaning private,
especially in methods. Apple reserves
the use of this convention. Use by
third parties could result in
name-space collisions; they might
unwittingly override an existing
private method with one of their own,
with disastrous consequences.
and since I'm not aware of any trailing underscore convention, I don't know why you shouldn't use just foo.
You are not supposed to use underscore as a prefix as per _foo - that is reserved for Apple (and keeps you from accidentally re-defining a variable you do not know about!)
I like foo_, but only if you are writing accessors. Otherwise I just use foo. However for memory uses alone, it's good practice to always use accessors and just declare the ones you do not want public in a private category in the implementation like so:
#interface MyClass ()
#property (nonatomic, retain) NSArray *myArray;
#end
#implementation
#synthesize myArray = myArray_;
#synthesize myPublicString = myPublicString_;
- (void) dealloc
{
[myArray_ release]; myArray_ = nil;
[myPublicString_ release]; myPublicString_ = nil;
}
....
#end
Since I seem to be in the minority, I'll go ahead and throw in my two cents in the interest of balance:
I like the underscore varieties. I think it makes the code semantics more readable at a glance. Sure, syntax highlighting can do that as well, but I've always preferred the IDE/theme independent approach. Once you're used to it, it's nice to have the little guy immediately set off the "directly accessing an ivar here" alarm in your head.
Obviously, this is incredibly subjective.
As an addendum, the underscore prefix is really only especially dangerous with method names, where collisions won't be immediately exposed by the compiler, but it is probably still better to go with the suffix, if you're an underscore fan.
In general terms, why would anyone name their private variables with any suffix or prefix, most of the modern day tools do a great job in colorize them differently anyway. I prefer simply foo.

iOS Singletons and Memory Management

I'm certain that I'm missing some fundamental understanding of iOS memory management and, despite lots of reading and searching, I'm still not getting it.
I use a singleton in my app that has info about the user currently signed into it, info accessed from multiple view controllers, etc. It has multiple ivars that are get and set throughout the app. They're declared and propertied in the .h file like so:
NSString *myString;
and are made retained like so:
#property (non atomic, retain) NSString *myString;
and synththesized in the implementation.
I get and set their values in methods in the singleton like this:
myString = #"value";
and
methodLocalString = myString;
In other places I include the singleton -- call it CurrentUser -- I import it:
#import "CurrentUser.h"
Outside of the singleton I get and set it like this:
[CurrentUser sharedCurrentUser].myString = #"Bob";
and
myOutsideString = [CurrentUser sharedCurrentUser].myString;
Most of the time this works great, with the values appropriately persisted from one getting or setting to another. The trouble is that sometimes when I get them that way I find that they've been released (crashing the app), which NSZombieEnabled thankfully tells me.
What I don't get is how his can happen. I thought the singleton was never released, and that therefor retained properties of the singleton would never be released. I'll note that the problem seems to be more common with non-real-object properties like NSDate and definitely-not-object properties like int and BOOL which can't be retained, but it happens with object properties as well.
What am I ignorant about here? And thanks for your patience.
Your problem is:
I get and set their values in methods
in the singleton like this:
myString = #"value";
When you assign directly to the iVar, instead of using the property syntax (self.myString = #"value"), you are bypassing the synthesized setter method, which means that the retain never happens.
Properties aren't magic. They're just a bit of syntactic sugar for the "." access, and the ability to have synthesized getter/setter methods to save you the tedium of writing your own.
self.myString = #"value";
is just shorthand for
[self setMyString:#"value"];
The synthesized setMyString method will do something like:
if (myString != newValue) {
[myString release];
myString = [newValue retain];
}
(assuming retain option on the #synthesize)
Don't use singletons. Your current problem is caused by a simple memory management misconception, but the singleton pattern will only give you more headache in the long run.

Why use 'self.' when its not forced?

I noticed a difference between the way I code (badly ;) ) and the code I see from others.
Can anybody explain why I see some people using
self.varname.anotherpropertie
When
varname.anotherpropertie
Seems to work just as well. I dont use self. a lot in my code. I'm wondering is this very bad or is there something that I need to learn to understand why its used so much by most people?
Thanks again,
-Code
They are different things. In a class where you have an instance variable named foo with a declared property also named foo, writing simply foo accesses the instance variable while self.foo goes through the getter method for the property (which might just return the instance variable or it might do more).
I'd suggest taking a look at the Declared Properties chapter of Apple's The Objective-C Programming Language for a full explanation of how it works and when to choose which option.
One gotcha that I've run into is the retain vs non-retain with properties.
So if you have a retained property like this:
#property (nonatomic, retain) NSString* myStr;
#synchronized myStr;
and you do something like this:
- (void) myMethod:(NSString*)inStr
{
myStr = inStr;
}
In this example you will not actually retain the string as your property is not invoked. If you change the assignment line to use the property (by using "self.") then the string would be retained (and the previous string would be released if non-nil).
self.myStr = inStr;
It takes some getting used to that properties are method calls, but once you start seeing them as such then the "self." syntax becomes much more clear. Hope that helps some.

Memory Management on the iPhone

I'm sorry to ask such a simple question, but it's a specific question I've not been able to find an answer for.
I'm not a native objective-c programmer, so I apologise if I use any C# terms!
If I define an object in test.h
#interface test : something {
NSString *_testString;
}
Then initialise it in test.m
-(id)init {
_testString = [[NSString alloc] initWithString:#"hello"];
}
Then I understand that I would release it in dealloc, as every init should have a release
-(void)dealloc {
[_testString release];
}
However, what I need clarification on is what happens if in init, I use one of the shortcut methods for object creation, do I still release it in dealloc? Doesn't this break the "one release for one init" rule? e.g.
-(id)init {
_testString = [NSString stringWithString:#"hello"];
}
There is a neat acronym to remember what you have to release
N.A.R.C - new, alloc, retain, copy.
If it's not created with alloc, new, copy, mutableCopy then you're not responsible for releasing it.
This site has some good quick overviews of things like memory management.
Here's a quote from cocoadevcentral:
If you create an object using the
manual alloc style, you need to
release the object later. You should
not manually release an autoreleased
object because your application will
crash if you do.
Just to clarify things a bit. When you get an object through N.A.R.C. as sylvanaar says you do need to release it. In other cases you are getting an autoreleased object that will be released automatically at some later time. That will be bad in the code you presented here, because you do want this string to stay around at least as long as your object. So you actually need to do an explicit retain to keep it alive for your object.
That is not directly answering your question, but rather anticipating the next one ;-)
If you set an attribute with an autorelease, the object in the attribute can die at anytime beyond the immediate scope. Convenience methods i.e. ones that start with a type: string, array, dictionary etc, return autoreleased objects. You only use autoreleased objects when you don't care whether or not they survive beyond the present scope.
What you really need to do in this case is use accessors, either the synthesized or custom, to manage your retention automatically.
If you do:
#property(nonatomic, retain) NSString *_testString; // .h
#synthesize _testString; //.m
then in code use the reference form:
self._testString = [NSString stringWithString:#"hello"];
... then the only place you have to release _testString is in dealloc. The compiler will create synthesized accessors which will automatically manage the properties memory for you.
By the way, you should not use underscores for names. Apple reserves underscore names for itself so you can get a naming collision.
In the first part of the example you do indeed have to have a release for the string somewhere.
In the second part of the example because its an autoreleased you don't need to call the additional release in the dealloc method. This will actually cause a crash as you are attempting to send a message to something that no longer exists...
On the contrary, you need to retain the object you get from stringWithString:. As you correctly noted, you don't own that object and thus don't need to release it. But because you don't own it, it's free to disappear at any time, leaving you with a crash if you're lucky (and a very odd bug if you're not). So you need to retain the object, and then you do need to release it in dealloc.
All of this is explained very well in the memory management guide. I suggest you read it over a couple of times. It's not very long or difficult, and once you internalize it, you'll never have to wonder again.
The rule is if you create an object with new, alloc, copy or you retain it, you need to release it. Objects created in any other way must not be released.
So in your specific case, you would not need to release your string created with stringWithString.
By the way, I would recommend the Cocoa and Objective-C: Up and Running book for learning more about things like this. Great introduction if you are new to Cocoa programming.