Do Setters have to have an argument - objective-c

I have written a setter that is not working as expected. I am reading in statistics from a file and populating the properties of my SVTeam object with these stats. However some of the properties need to be calculated (as they are not supplied in the files). One of these properties holds the home winning percentage for a given team. I do not need to supply an argument for the setter. Two questions:
Since I'm NOT supplying an argument in my setter is it still truly a setter in an objective-c sense?
Even it if is not a true setter why does the code below still leave the properties as null?
SVTeam.h
#interface SVTeam : NSObject
#property (weak, nonatomic) NSNumber *homePercentage;
...
...
SVTeam.m
#import "SVTeam.h"
#implementation SVTeam
#synthesize homePercentage = _homePercentage;
...
...
-(void) setHomePercentage
{
float wins = [_homeWins floatValue];
float losses = [_homeLosses floatValue];
float ties = [_homeTies floatValue];
float winPercentage = wins / (wins+losses+ties);
self.homePercentage = [NSNumber numberWithFloat:winPercentage];
}

Since homePercentage is a calculated value based on other properties you could make it a readonly property and you would have your calculation logic in the getter instead. If you leave it as a setter then your consumers would have to make sure to call the setter first and call the getter to retrieve the value.
#property(nonatomic,readonly) NSNumber *homePercentage;
And your getter definition would be
- (NSNumber *)homePercentage
{
...
return [NSNumber numberWithFloat:winPercentage];
}

To expand on Garfield81's answer:
If you want to override the setter synthesized by clang for you homePercentage property, you need to implement -(void)setHomePercentage:(NSNumber *)homePercentage; in your class.
Apple documentation on properties.
To answer your two questions:
1) since I'm NOT supplying an argument in my setter is it still truly a setter in an objective-c sense?
No. The synthesized setters takes an unique argument of the same type of the propery and are named set<CapitalizedPropertyName>. What you did is declare a new method.
2) even it if is not a true setter why does the code below still leave the properties as null
There is not apparent reason for homePercentage to stay nil (not null) from the code you provided. Are you sure your custom method gets called? (remember that when using the dot notation (self.homePercentage), this is -(void)setHomePercentage:(NSNumber *)homePercentage; which is called, not your -(void)setHomePercentage;).
Note also that you don't need to add #synthesize homePercentage = _homePercentage; unless you override both the getter and the setter.

Related

Updating a class with readonly properties in Objective-C

What is a good pattern for creating and updating a class with readonly properties? An example for such a class
#interface ReadOnlyClass : NSObject
#property (nonatomic, assign, readonly) NSUInteger number;
#end
It is not necessary for the class user to call the init constructor (although this is not really possible to avoid in Objective-C) or anything else. Apple uses this pattern e.g. in CMLogItem or CLLocation. So, how can I change/update the value of number in a good manner?
If I understood you correct, number is a computed property or – to have a better term – depending property. The value of number depends on other properties that can change themselves. Correct?
Usually you simply write an explicit setter for this:
-(NSUInteger)number
{
return /* your calculation */;
}
For example: You have another property playerName and you want to return the number of characters. (Okay, not very exiting, but I need an example.)
-(NSUInteger)number
{
return [self.playerName length];
}
Please note: Since you overwrite all methods declared for the read-only property, no ivar is synthesized.
If the calculation is expensive or the getter is executed more often than the setters for the changeable properties (playerName) by far, it can be an optimization to change the property inside the class into a read-write property and set the value, every time the changeable properties are changed.
#interface ReadOnlyClass ()
#property (readwrite, …) NSUInteger number;
…
#end
// number is synthesized in this case
-(void)setPlayerName:(NSString*)playerName
{
_playerName = playerName;
self.number = [playerName length];
}
I believe the best pattern matching for what ask is the Builder Pattern.
EG : You have your read only property which is the result, then some function calculate. You can set various parameters inside like
-(void) setMathExpression:(NSString) aExpression;
-(void) calculate;
Then the user can set an expression, call calculate then get the result from the readonly property.

property without retain with example

if we use a property without the "retain", what does it change? i have this example :
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithCoordinate:(CLLocationCoordinate2D) coordinate;
in the .m :
-(id)initWithCoordinate:(CLLocationCoordinate2D)coord{
coordinate = coord;
return self;
}
the "retain" is normally used for the setter, isn't it? so here, we use the setter, in initWith..., but we don't use "retain"... any idea?
Thanks
CLLocationCoordinate2D is not an Objective C object, so attempting to send retain and release to it doesn't make sense.
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
This declares an assign read only property, which is the only correct thing to do for a property with a plain C type. Additionally you have said it is nonatomic which means that there is no code to synchronize the property. Since the property is a struct consisting of two 64 bit values, that probably means that you can get an inconsistent result back if you read the property at the same time as some other thread is changing it.
the "retain" is normally used for the setter, isn't it? so here, we use the setter, in initWith...
No, you don't actually. The line
coordinate = coord;
actually assigns the instance variable directly. However, this is what you want in this case. If the property was not read/write and was an Objective-C object type, it would still be assigning the instance variable directly. In that case, you'd need one of the following.
[self setCoordinate: coord];
or
self.coordinate = coord;
or
coordinate = [coord retain]; // in init only
By the way, your init is wrong. It should follow the pattern:
-(id)initWithCoordinate:(CLLocationCoordinate2D)coord{
self = [super init]; // assuming init is the designated initialiser of the super class
if (self != nil)
{
coordinate = coord;
}
return self;
}
In your specific case, readonly means that you class allocates the object and then gives access to it through a property that does not allow this property to be changed from outside.
In general, the object will be nevertheless retained by the class when it allocates it, and released when dealloc is executed.
In your case, the object of type CLLocationCoordinate2D is copied when assigning to the ivar:
coordinate = coord;
because it is not a pointer object, rather a simple struct made out of 2 doubles:
typedef double CLLocationDegrees;
typedef struct {
CLLocationDegrees latitude;
CLLocationDegrees longitude;
} CLLocationCoordinate2D;
So, that is the reason why you don't see any retain in the code. If instead of being a CLLocationCoordinate2D object, it had been an NSString you would have probably needed a retain when doing the assignment to the ivar. (I say "probably" because it all depends on the ownership of the assigned object).
The retain property is used for objects that need to be (surprise) retained. That is: your objects needs the object assigned to the property to stay around, it may not be deallocated.
In your case, it wouldn't change anything as a struct, not an object.
But what you're using in the cited code is readonly, and that means there is no setter, only a getter.

Objective-C, interface declarations with properties

In the following common sample,
////
#interface MyObject : NSObject
{
#public
NSString * myString_;
}
#property (assign) NSString * myString;
#end
#implementation MyObject
#synthesize myString = myString_;
#end
////
why declare myString_ in the interface at all?
I ask because we can still get and set myString in the implementation using self.myString, [self myString], self.myString = ... and [self setMyString:...] and in fact we must if instead it's being retained.
This is a matter of preference/convention for some. By default, doing:
#property (assign) NSString * myString;
...followed by:
#synthesize myString;
...will give you three things. You get a setter method that can be accessed as self.myString = #"newValue" or [self setMyString:#"newValue"], a getter method that can be accessed as NSString* temp = self.myString or NSString* temp = [self myString], and an instance variable named myString that be be accessed directly inside of your class (i.e. without going through the getter and setter) and used to set and get the property value, and which is used internally to back the property.
If you like you can do #synthesize myString = someOtherVarName, and then you still get the setters and getters just as before, but instead of the myString instance variable the someOtherVarName instance variable is used to back the property, and no myString variable is created.
So why ever use the more verbose syntax? There is never any case that requires that you do so, but some people prefer to do so when dealing with properties that are declared retain or copy. The reason for this being that setting a property declared retain or copy via its generated setter method will affect the retain-count of the object being set/unset. Doing the same thing by accessing the instance variable directly will not.
So by aliasing the instance variable to something else, you can make a distinction in the code along the lines of "anything that does xxx.myString = Y is modifying the retain count, while anything that does someOtherVarName = Y is not". Again, it's not necessary to do this, but some people prefer to.
You should be able to skip it. Modern compilers allow that.
When you define a property, you are actually declaring how the getter and setter methods are constructed for a particular instance variable. Earlier it needed the instance variable to be defined so you declared it. It also allowed the property name to differ from the instance variable name via #synthesize myProperty = myIVar;. Now you don't need to do this as the modern compilers generate the instance variable for you.
The dot syntax is actually a convenience thing as you would've noticed. It doesn't directly refer to the instance variable but the methods myProperty and setMyProperty:. You can even call myArray.count where count isn't a property (I wouldn't recommend it even though lot of people seem to like it).
While there is a difference between the two, the gap seems to be slowly closing.
That's just a problem about point of view. If you access ivar directly, it's you're accessing it internally. If you're using property, you're not accessing ivar (semantically). You're using accessing method of the object. So you're handling the self as like external object which the internal is unknown.
This is encapsulation problem of Object-Oriented paradigm.
And I recommend some tricks when using properties.
The ivar declaration is optional, not required. Compiler will generate it automatically.
You should set the ivar as #protected or #private to encapsulate it correctly. (at least there is no reasonable reason)
I recommend to use nonatomic if you don't need threading lock when accessing the property. Threading lock will decrease performance greatly, and may cause strange behavior in concurrent execution code.
You can use this code to do same thing.
#interface MyObject : NSObject
#property (assign,nonatomic) NSString * myString;
#end
#implementation MyObject
#synthesize myString;
#end
And this will be transformed roughly something like this.
#interface MyObject : NSObject
{
#private
NSString* myString; // Ivar generated automatically by compiler
}
#end
#implementation MyObject
// Methods with thread synchronization locking generated automatically by compiler.
- (NSString*)myString { #synchronized(self) { return myString; } }
- (void)setMyString:(NSString*)newMyString { #synchronized(self){ myString = newMyString; } }
#end
In fact, I'm not sure about synchronization lock with assign behavior directive, but it's always better setting it nonatomic explicitly. Compiler may optimize it with atomic operation instruction instead of locking.
Here is reference document about the properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17
With the modern Obj-C runtime, declaring the ivar is more of a formality than anything else. However, there are some memory management things to keep in mind.
First, the property declaration for an object type is usually retain, or for strings it may be copy. In either case, the new object is retained.
Given the following code:
NSString *string = [[NSString alloc] init];
myString_ = string;
self.myString = string; // If the property was retain or copy
The second assignment would leak; the first would not. This is because the property would retain something that already has a retain count of 1—it is now at 2. When you release the property in dealloc, the count goes to 1, not 0, so it won't be released. With the first option, however, the retain count stays at 1, so dealloc brings it down to 0.
In your example, leaving the property as assign will make the ivar declaration a formality.

#property question

In my implementation I have getters and setters like below. I want to use properties and synthesize the getters and setters but have a few questions.
- (NSString *)title {
return title;
}
- (void)setTitle:(NSString *)value {
if(title != value) {
[title release];
title = [value retain];
}
}
If I was to convert that to a property, what attributes would I use? Am I right in thinking:
readwrite so both getters and setters are present
retain so that it increase the retain value of the value string so the object don't lose it.
Am I right with the above?
One final thing. I have the method below ...
- (void)setReleaseDate:(NSString *)value {
// YYYY-MM-DD HH:MM:SS +HHMM
if([releaseDate description] != value) {
[releaseDate release];
releaseDate = [[NSDate alloc] initWithString:value];
}
}
Am I right in thinking I still have to include that method because it contains code that the synthesized getter would not include?
Thanks.
For your title property, you can declare it in your class interface as follows:
#property (nonatomic, retain) NSString* title;
Which is the same as the following:
#property (readwrite, nonatomic) NSString* title;
readwrite is a default setting. Most of the time you will want setters for your properties, so for the times when you don't you would use the non-default readonly to specify this.
The nonatomic part basically means that the accessors will be faster, and is typically used. You can find out more information about this here: What does the property "Nonatomic" mean?.
For your second question, you can implement your own accessors if you wish. If you do this then it kind of 'overrides' the accessor that would be generated by Objective-C. Remember that you have to keep to the naming conventions. So in your example, the "setReleaseDate:" method you've defined would be used for the setter method for the property "releaseDate" - which is completely correct! :) The problem you have though is that you're passing an *NSString** to set the date, which means that this method won't override the default setter that would be used if you synthesized the property. You have to pass a value of the same type as the one you're setting as the single argument, so for this case you would have to pass an *NSDate**.
You must also ensure that if you provide your own implementation of an accessor that it does what is declared in the interface. I presume your releaseDate property should be declared as retain.
Your assertion about using readwrite as well as retain is correct as it would create semantically equivalent code to what you have posted.
The releasedate property setter can't be synthesized as you're transforming a NSString into a NSDate to store it, that also avoids common issues with NSString properties, for which you'd better use copy to avoid problems with NSMutableString.
Other than that, your code is fine, except that for string comparison you may want to replace the simple pointer check != with isEqualToString, see Comparing Strings in Cocoa.
It is common, though not always required, to use copy semantics for NSString properties, to avoid issues with NSMutableString objects being changed behind your back.
Otherwise, you seem to be pretty much on top of it.

What is the difference between ivars and properties in Objective-C

What is the semantic difference between these 3 ways of using ivars and properties in Objective-C?
1.
#class MyOtherObject;
#interface MyObject {
}
#property (nonatomic, retain) MyOtherObject *otherObj;
2.
#import "MyOtherObject.h"
#interface MyObject {
MyOtherObject *otherObj;
}
#property (nonatomic, retain) MyOtherObject *otherObj;
3.
#import "MyOtherObject.h"
#interface MyObject {
MyOtherObject *otherObj;
}
Number 1 differs from the other two by forward declaring the MyOtherObject class to minimize the amount of code seen by the compiler and linker and also potentially avoid circular references. If you do it this way remember to put the #import into the .m file.
By declaring an #property, (and matching #synthesize in the .m) file, you auto-generate accessor methods with the memory semantics handled how you specify. The rule of thumb for most objects is Retain, but NSStrings, for instance should use Copy. Whereas Singletons and Delegates should usually use Assign. Hand-writing accessors is tedious and error-prone so this saves a lot of typing and dumb bugs.
Also, declaring a synthesized property lets you call an accessor method using dot notation like this:
self.otherObj = someOtherNewObject; // set it
MyOtherObject *thingee = self.otherObj; // get it
Instead of the normal, message-passing way:
[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it
Behind the scenes you're really calling a method that looks like this:
- (void) setOtherObj:(MyOtherObject *)anOtherObject {
if (otherObject == anOtherObject) {
return;
}
MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
otherObject = [anOtherObject retain]; // put the new value in
[oldOtherObject release]; // let go of the old object
} // set it
…or this
- (MyOtherObject *) otherObject {
return otherObject;
} // get it
Total pain in the butt, right. Now do that for every ivar in the class. If you don't do it exactly right, you get a memory leak. Best to just let the compiler do the work.
I see that Number 1 doesn't have an ivar. Assuming that's not a typo, it's fine because the #property / #synthesize directives will declare an ivar for you as well, behind the scenes. I believe this is new for Mac OS X - Snow Leopard and iOS4.
Number 3 does not have those accessors generated so you have to write them yourself. If you want your accessor methods to have side effects, you do your standard memory management dance, as shown above, then do whatever side work you need to, inside the accessor method. If you synthesize a property as well as write your own, then your version has priority.
Did I cover everything?
Back in the old days you had ivars, and if you wanted to let some other class set or read them then you had to define a getter (i.e., -(NSString *)foo) and a setter (i.e., -(void)setFoo:(NSString *)aFoo;).
What properties give you is the setter and getter for free (almost!) along with an ivar. So when you define a property now, you can set the atomicity (do you want to allow multiple setting actions from multiple threads, for instance), as well as assign/retain/copy semantics (that is, should the setter copy the new value or just save the current value - important if another class is trying to set your string property with a mutable string which might get changed later).
This is what #synthesize does. Many people leave the ivar name the same, but you can change it when you write your synthesize statement (i.e., #synthesize foo=_foo; means make an ivar named _foo for the property foo, so if you want to read or write this property and you do not use self.foo, you will have to use _foo = ... - it just helps you catch direct references to the ivar if you wanted to only go through the setter and getter).
As of Xcode 4.6, you do not need to use the #synthesize statement - the compiler will do it automatically and by default will prepend the ivar's name with _.