#property, setter and getter question? - objective-c

NSString *statusValue;
NSString *currentValue;
#property(retain, nonatomic) NSString *statusValue;
#property(retain, nonatomic) NSString *currentValue;
#synthesize statusValue;
#sythnesize currentValue;
Given the above, if I am setting one variable to another should I be doing ...
[self setStatusValue: currentValue];
or should I use the property again and use ...
[self setStatusValue: [self currentValue]];
I suppose the latter (although maybe overkill) does tell the reader that we are using one of the objects instance variables and not some local variable.
just curious really, I was going with the bottom one, but just wanted to check before someone looked at my code and when "what the hell" :)
gary

Both work just fine. Which one you use may depend on the side-effects you wish. For example, by using [self currentValue], you may fire off willAccessValueForKey: and didAccessValueForKey: KVO notifications, but only if somebody's actually observing that property, and only if it's an NSManagedObject subclass. Usually there aren't any major side effects.
Personally, I'd probably use the latter example, just so that I don't have to worry about changing the name of an iVar in 30 places if I decide to change it (of course, the Refactor->Rename tool would be the right to use in that situation, but still).

I use the latter in the absence of a compelling reason not to. That way it works with overridden accessors, changed implementations, etc. without any changes. For example, maybe I decide to switch from storing the statusValue as a string and instead store a Status object with statusValue going through that. If I'm manually accessing the ivar all over the place, I have to change all of them. If instead I'm going through the class's public interface, I only have to change the one accessor method.

This works and is more expressive IMO:
self.statusValue = currentValue;

Related

Different Ways To Declare Objective C Instance Variables [duplicate]

I have been unable to find any information on this topic and most of what I know about it has come by complete accident (and a few hours of trying to figure out why my code wasn't working). While learning objective-c most tutorials I have found make variables and properties with the same name. I don't understand the significance because it seems that the property does all the work and the variable just kind of sits there. For instance:
Test.h
#interface Test : NSObject {
int _timesPlayed, _highscore;
}
#property int timesPlayed, highscore;
// Methods and stuff
#end
Test.m
#implementation Test
#synthesize timesPlayed = _timesPlayed;
#synthesize highscore = _highscore;
// methods and stuff
#end
What I know
1) Okay so today I found out (after hours of confusion) that no matter how much changing you do to the properties highscore = 5091231 it won't change anything when you try to call [test highscore] as it will still be returning the value of _highscore which (I think) is the ivar that was set in test.h. So all changing of variables in test.m needs to be changing _highscore and not highscore. (Correct me if I'm wrong here please)
2) If I understand it correctly (I probably don't) the ivars set in test.h represent the actual memory where as the #properties are just ways to access that memory. So outside of the implementation I can't access _highscore without going through the property.
What I don't understand
Basically what I don't get about this situation is whether or not I need to use the ivars at all or if I can just use #property and #synthesize. It seems like the ivars are just extra code that don't really do anything but confuse me. Some of the most recent tuts I've seen don't seem to use ivars but then some do. So is this just a coding preference thing or is it actually important? I have tried searching through Apple's Documentation but I get rather lost in there and never seem to find what I'm looking for. Any guidance will be greatly appreciated.
You can think of the syntax for synthesizing properties as #synthesize propertyName = variableName.
This means that if you write #synthesize highscore = _highscore; a new ivar with the name _highscore will be created for you. So if you wanted to you could access the variable that the property is stored in directly by going to the _highscore variable.
Some background
Prior to some version of the compiler that I don't remember the synthesis statement didn't create the ivar. Instead it only said what variable it should use so you had to declare both the variable and the property. If you synthesized with a underscore prefix then your variable needed to have the same prefix. Now you don't have to create the variable yourself anymore, instead a variable with the variableName that you specified in the synthesis statement will be created (if you didn't already declare it yourself in which case it is just used as the backing variable of the property).
What your code is doing
You are explicitly creating one ivar called highscore when declaring the variable and then implicitly creating another ivar called _highscore when synthesizing the property. These are not the same variable so changing one of them changes nothing about the other.
Should you use variables or not?
This is really a question about preference.
Pro variables
Some people feel that the code becomes cleaner if you don't have to write self. all over the place. People also say that it is faster since it doesn't require a method call (though it is probably never ever going to have a measurable effect on your apps performance).
Pro properties
Changing the value of the property will call all the necessary KVO methods so that other classes can get notified when the value changes. By default access to properties is also atomic (cannot be accessed from more then one thread) so the property is safer to read and write to from multiple thread (this doesn't mean that the object that the property points to is thread safe, if it's an mutable array then multiple thread can still break things really bad, it will only prevent two threads from setting the property to different things).
You can just use #property and #synthesize without declaring the ivars, as you suggested. The problem above is that your #synthesize mapped the property name to a new ivar that is generated by the compiler. So, for all intents and purposes, your class definition is now:
#interface Test : NSObject {
int timesPlayed;
int highscore;
int _timesPlayed;
int _highscore;
}
...
#end
Assigning a value directly to the ivar timesPlayed will never show up if you access it via self.timesPlayed since you didn't modify the correct ivar.
You have several choices:
1 Remove the two ivars you declared in your original post and just let the #property / #synthesize dynamic duo do their thing.
2 Change your two ivars to be prefixed by an underscore '_'
3 Change your #synthesize statements to be:
#implemenation Test
#synthesize timesPlayed;
#synthesize highscore;
...
I typically just use #property and #synthenize.
#property gives the compiler and the user directions on how to use your property. weather it has a setter, what that setter is. What type of value it expects and returns. These instructions are then used by the autocomplete (and ultimately the code that will compile against the class) and by the #synthesize
#synthesize will by default create an instance variable with the same name as your property (this can get confusing)
I typically do the following
#synthesize propertyItem = _propertyItem;
this will by default create a getter and a setter and handle the autorelease as well as create the instance variable. The instance variable it uses is _propertyItem. if you want to access the instance variable you can use it as such.
_propertyItem = #"Blah";
this is a mistake tho. You should always use the getter and setter. this will let the app release and renew as needed.
self.propertyItem = #"Blah";
This is the better way to handle it. And the reason for using the = _propertyItem section of synthesize is so you cannot do the following.
propertyItem = #"Blah"; // this will not work.
it will recommend you replace it with _propertyItem. but you should use self.propertyItem instead.
I hope that information helps.
In your example, #synthesize timesPlayed = _timesPlayed; creates a new ivar called _timesPlayed and the property refers to that ivar. timesPlayed will be an entirely separate variable with no relation whatsoever to the property. If you just use #synthesize timesPlayed; then the property will refer to timesPlayed.
The purpose of the underscore convention is to make it easier to avoid accidentally assigning directly to an ivar when you want to be doing it through the property (i.e. through the synthesized setter method). However, you can still acces _timesPlayed directly if you really want to. Synthesizing a property simply auto-generates a getter and setter for the ivar.
In general you do not need to declare an ivar for a property, although there may be special cases where you would want to.
This may be an old question.. but in "modern times", #synthesize- is NOT necessary.
#interface SomeClass : NSObject
#property NSString * autoIvar;
#end
#implementation SomeClass
- (id) init { return self = super.init ? _autoIvar = #"YAY!", self : nil; }
#end
The _underscored backing ivar IS synthesized automatically... and is available within THIS class' implementation, directly (ie. without calling self / calling the automatically generated accessors).
You only need to synthesize it if you want to support subclass' ability to access the _backingIvar (without calling self), or for myriad other reasons, described elsewhere.

Syntax help, why put '_' before variables?

I've been running though some tutorials and often times I will see something like this.
in the .h
UIButton *_loginButton;
#property (retain) IBOutlet UIButton *loginButton;
Then in the .m it will be something like...
#synthesize loginButton = _loginButton;
So my question is what benefit does putting an _ before do? or why is it common practice? and lastly should I be doing this as well?
It's a convention that people sometimes use to denote private instance variables, or to separate instance variables from properties. You'll sometimes see names with a leading underscore used for private functions or methods. As far as I know, Apple reserves that convention for its own use and recommends that you not use it in order to avoid name collisions. For that reason, you'll sometimes also see names that have a trailing underscore instead of a leading one, i.e. foo_ instead of _foo.
Because its a local variable.
Some companies have internal requirements to write the local variables with _
I don't know which version this started with, but I've noticed that you don't need to have a actual variable declaration at all if you're just going to represent it as a property.
// Interface
#property (retain) IBOutlet UIButton *loginButton;
// Implementation
#synthesize loginButton
And then you can just use the property:
loginButton = (....)
self.loginButton = (...)
[self setLoginButton:(...)]
etc...
Now, whether one way or another is The Right Way depends on personal taste really. For something like this, it usually always falls in the "stay consistent and following whatever coding standards are in place by you (sole developer) or your company/group/team)" category.

Is it ok to call release on a property in Objective C?

I've been teaching myself Objective C recently, and have noticed the following pattern used a lot in tutorials and sample code (including samples from the Apple site).
UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];
I was just wondering though, it seems a bit of a waste to create a new variable, just to set a property. I've also seen the following pattern used too, but from what I understand its considered bad form to use autorelease on an iOS device as the autorelease pool takes up quite a bit of overhead which might not be good on a mobile device
self.uiView = [[[UIView alloc] init] autorelease];
I've been toying with using the following pattern recently, which sets the property, and then calls release on the property (to decrease the reference counter on the property itself).
self.uiView = [[UIView alloc] init];
[self.uiView release];
I've managed to use it on a few ViewControllers with no ill effects, but is this valid code, or am I missing something which makes it a bad idea?
The property getter is a method, and it does not have to return an ivar, it may actually get its return value anywhere, so you could release that, but it could be an autoreleased value already. If that is the case, you're in trouble.
IOW, if a property getter would do something like (not usual, but possible and valid):
- (NSString *) helloString
{
return [[myStringIVar copy] autorelease];
}
and you do:
[self.helloString release];
then you failed in two ways:
You did not release the ivar you wanted to release
You release an autoreleased object
IMO, it is better to release the ivar directly:
[myStringIVar release];
If the implementation of the property getter is simply to return the reference to the underlying ivar, then it is perfectly equivalent and you simply decrease the retain count of the allocated object.
On the other hand, if you can't be sure what the getter does (what if it returns something else than the ivar, e.g. some calculated result etc.), it may be dangerous.
No. It's not valid.
It will probably work on most retain properties but not necessarily. It will probably break on copy properties and assign properties.
Properties are just a pair of methods, one of which sets an abstract entity and one which gets it. There is absolutely no guarantee in general that the getter will give you the exact same object that you just passed to the setter. For instance, if you pass a mutable string to an NSString copy property, you definitely won't get back the same object.
Use either of the first two patterns. The first one does not waste anything. It is likely the local variable will only ever exist in a register. The overhead of the second will only last as long as the next autorelease pool drain and is only a few bytes (bear in mind that the actual object will last as long as self in any case).
It's not valid, and even in the cases where it does work its a bit "ugly" the other two are just to fix the property's retain characteristic from making the retain count 2 after having an alloc already making the retain count 1.
I tend to do what you described in the first example or the following.
in my #interface
#property (nonatomic, retain) UIView *uiView;
in my #implementation
#synthesize uiView = _uiView;
then when I setup the property.
_uiView = [[UIView alloc] init];
Thinking in terms of the reference counter, nothing is wrong with calling release using the property value. However, there are a few things, which I (personally) would dislike:
The property syntax is really just syntactic sugar for method calls. So, what your code really looks like, is
[self setUiView: [[UIView alloc] init]];
[[self uiView] release];
Another thing here might be more due to me thinking in strange ways, but I like to think of the reference counts as actually being related to references. A local variable holding a pointer to my object is such a reference. Having it present in the code reminds me, that I have something to do in order to clean things up properly (or, if not, at least write a short comment, why I don't have to clean up).
Directly going through the property forces me to think in terms of reference counts instead, which I don't like.

Retain and self with NSMutableArray

In my .h file I have a NSMutableArray *locationsArray defined with a property as follows
#property (nonatomic, retain) NSMutableArray *locationsArray
In my .m file I was displaying a table view, this loaded fine until I tried to roll-up at which point I it crashed with bad access. This was due to the locationsArray not being retained.
This line of code fixed my problem in the .m
locationsArray = [[Locations loadLocations] retain] (#1)
This line of code also fixed the same problem
self.locationsArray = Locations.loadLocations (#2)
I have a couple of questions I need clarification on
is this the correct way to set this value, should I be doing an alloc init, alloc initwithArray?
Comming from a java world I understand self is this, or at least I thought I did...What is different in objective C that the locationsArray without the self is not being retained without me adding the retain.
Obviously I got it working but it took as while and am still a little confused as to why. any help would be appreciated.
Yes, if you set the instance variable (locationsArray) directly, you need to retain the value to keep it. You can either do that as you've done, or alloc/init it directly, which also means that you have a retain ownership of it.
self is indeed equivalent to this in other OO languages. But there's a semantic difference in Obj-C between referring to an ivar "naked" like in your first example, and referring to it as self.locationsArray in the second. The former behaves how you'd imagine, but the latter is actually a syntactic shortcut for [self setLocationsArray: ... ] which does the retain automatically for you, because you've marked the property as being retain.
This last point is really subtle, and (to my view) not expected or obvious behavior. If you're still fuzzy on it, go back to the Apple docs. Really important to get this.

when to use "willChangeValueForKey" and "didChangeValueForKey"?

I saw these lines in a demo project, but I couldn't understand why it did that.
[self willChangeValueForKey:#"names"];
[self didChangeValueForKey:#"names"];
It called didChangeValueForKey immediately after willChangeeValueForKey.
Does it make any sense?
Furthermore, when should be the right time to call this two methods?
Thanks a lot!! :)
This is, in fact, an anti-pattern. You should not call -willChangeValueForKey: followed by -didChangeValueForKey: without any intervening actual property change. In some cases, doing so can mask KVO problems elsewhere in your code and force observers to update their state related to the property in question. Ultimately, however, you (or the author of the example you cite) should fix the rest of the code so that this anti-pattern is unnecessary.
The correct usage of -will|didChangeValueForKey: is when you are modifying a property without using KVC-compliant accessors/setters such that the KVO mechanism would not notice the change. For a contrived example, consider modifying the backing instance variable for an attribute directly:
#interface Foo
{
int bar;
}
#end
#implementation Foo
- (void)someMethod
{
bar = 10;
}
#end
KVO observers that had registered for notification of changes in the bar property would not recieve notification of the change to bar in -someMethod. To make the KVO machinery work, you could modify -someMethod:
- (void)someMethod
{
[self willChangeValueForKey:#"bar"];
bar = 10;
[self didChangeValueForKey:#"bar"];
}
Of course, it would be better to use a #property declaration and to use KVC-compliant accessors/setters (either manually coded or #synthesized), but this is a contrived example.
KVO will operate correctly with custom setters for properties; this has always been the case for NSObject-derived classes. The runtime machinery looks for an invocation of the relevant setter method, and implicitly calls "willChangeValueForKey" prior to executing the setter, then implicitly calls "didChangeValueForKey" after the setter completes.
You can disable this automatic behavior if you wish to have more fine-grained control over KVO notifications. As mentioned above, readonly properties whose value you change by modifying the backing ivar, or whose values are derived by calculation, are places where you would use the manual notifications (although there is a mechanism, keyPathsAffectingValueFor, where you can tell the runtime that the value of a property is dependent on the change of another property, and it will send the change notification as appropriate.) To disable the automatic behavior on a per-property basis, you put in a class method + (BOOL) automaticallyNotifiesObserversOf and return NO.
I often disable automatic KVO notifications, because I have found that a KVO notification is generated when invoking a setter, even if the value of the property is being set to the same as its current value (e.g. no change). I wish to suppress the pointless notification for efficiency's sake:
+ (BOOL)automaticallyNotifiesObserversOfMyProperty
{
return NO;
}
- (void)setMyProperty:(NSInteger)myProperty
{
if(_myProperty != myProperty)
{
[self willChangeValueForKey:#"myProperty"];
_myProperty = myProperty;
[self didChangeValueForKey:#"myProperty"];
}
}
A good discussion can be found in the NSKeyValueObserving.h header, that you can navigate to by CMD+clicking on the method names "willChangeValueForKey" and "didChangeValueForKey" in XCode.
Those have to do with manually controlling key value observing. Normally the system takes care of it but these allow you some control. Look at this documentation to understand when and how to use them here.
Agree with Barry. I just meet the same problem. Here is a case of using those two methods.
I declared a readonly property. So I can't use the property's accessor to change the value.
#property (nonatomic, readonly) BOOL var;
When I want to change the "var", I need to call these two methods manually. Otherwise, observers won't get notified.
self willChangeValueForKey:#"var"];
var = YES;
[self didChangeValueForKey:#"var"];
If you want to do stuff just before the value gets changed, use willChangeValueForKey.
If you want to do stuff just after the value gets changed, use didChangeValueForKey.
Edit: ignore me, was reading too fast - Barry is right :-)
Be really careful when overriding didChangeValueForKey:. The best thing is not to do it at all. But if you do, make sure you call super, otherwise you will have a memory leak as demonstrated here: https://github.com/jfahrenkrug/KVOMemoryLeak
if you rewrite property getter methods, please use it.
#property (assign, nonatomic, getter=isLogined) BOOL logined;
Posting this in July 2013, and it no longer seems to be necessary to call will/didChangeValueForKey. It seems to be taken care of automatically, even if you have a custom setter.