Guidelines for using properties vs methods - objective-c

I often have a hard time deciding if certain data should be exposed through a property or a method. You can say "use properties for object state", but that's not very satisfying. Take this example for instance:
- (NSString *)stringOne
{
return _stringOne;
}
- (NSString *)stringTwo
{
return _stringTwo;
}
- (NSString *)mainString
{
return [_stringOne length] > 0 ? _stringOne : _stringTwo;
}
It's clear that stringOne and stringTwo should be properties because they are clearly object state. It's not clear, however, if mainString should be a property. To the end user mainString acts like state. To your object, mainString is not state.
This example is contrived but hopefully you get the idea. Yes, properties are nothing more than a convenient way to create getters and setters but they also communicate something to the user. Does anyone have decent guidelines for deciding when to use a property vs a method.

Hiding the split between "true" state (string1 and string2 in your example) and "dynamic" state (mainString) is, I would say, exactly what properties are for.
The canonical example would probably be an object that represents a person, with given and family names as "state". A third piece of state, "full name" can be presented from those two pieces, but clients have absolutely no reason to know whether the full name is constructed on demand, or is created and stored when both of its pieces are set. It simply doesn't matter.
Properties are an interface -- what bits of data does this class provide to its clients (and what can the clients configure about the class)? The implementation of each property is encapsulated and does not affect its status as a property.
In ObjC, of course, we use methods to access properties. Other methods, however, represent actions that an object can take, possibly being passed some piece of data to operate on.

Another consideration to take into account : do you want to store the value of the property ? (via NSCoding or in Core Data for example)
I guess you NEED to create properties for things you need to "save" (in "encodeWithCoder" for instance. Deciding what you want to put in encodeWithCoder could help you decide which way you want to define things).
For things you don't need to save and can recalculate easily, you have the choice between a method and a readonly property (which is equivalent under the hood : a readonly property only creates a getter accessor method, and does not have an instance variable to back it). So that's more a question of style.
Speaking of style, if you use dot notation for properties only (as I do), you'd maybe wonder :
- do I want to access the full name as foo.fullName, and not make a difference with other properties like foo.firstName and foo.lastName ?
- or do you want to make a difference by accessing the full name with [foo fullName], showing to the world that this is calculated ?
I created an app for following stock quotes, and the model was inspired from an example in the Big Nerd Ranch book about Objective C (good read, by the way).
Here is how properties and methods are defined :
// properties
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *symbol;
#property (nonatomic, copy) NSString *currency;
#property (nonatomic, copy) NSString *market;
#property (nonatomic) int numberOfShares;
#property (nonatomic) double purchaseSharePrice;
#property (nonatomic) double currentSharePrice;
// Stock Calculation methods
- (double)costInLocalCurrency; // purchaseSharePrice * numberOfShares
- (double)valueInLocalCurrency; // currentSharePrice * numberOfShares
- (double)gainOrLossInLocalCurrency // valueInLocalCurrency - costInLocalCurrency
You can see that they are clearly distinguished.
The BNR does not use dot notation at all in their book, so it would all look the same : [foo currentSharePrice] or [foo valueInLocalCurrency], but as I use dot notation for properties, I would make a difference in style between foo.currentSharePrice and [foo valueInLocalCurrency].
Hope this is helpful.

By design, you should always respect the end user - if you think it's object state for the user of your class (which it apparently is), then go ahead and make a property out of it.

Related

Key-Value Coding with a key of 'description'

I am using Key-Value Coding to simplify updating instances of a model class:
#interface NewsItem : NSObject
{
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *link;
#property (nonatomic, copy) NSString *date;
using:
SEL selectorName = NSSelectorFromString(elementName);
if ([self.newsItem respondsToSelector:selectorName])
{
NSString *sanitisedElement = [self sanitiseElement:self.currentElementData];
[self.newsItem setValue:sanitisedElement forKey:elementName];
}
This works well but the 'description' property doesn't 'smell' right to me as it has overridden the base NSObject description getter (+ (NSString *)description). If the description getter is invoked now it will return irrelevant information when the caller would be expecting a description of the class.
Is it possible to safely proceed with Key-Value Coding for this class (given that I am bound to these property names by the external data source)? Or would it be wise to change the property names and manually check keys/set values instead?
You could override description in your class. This method is usually used only for debugging
and no caller can expect a specific output of that method.
But I see more general problems in your code. It is only checked that a method with the
given name exists. This does not imply that this method corresponds to a property, and even then, it does not imply that there is a setter for that property.
For example, every NSObject responds to the selector "init", so if the external
data source sends that key as "elementName", your code would immediately crash.
Therefore, an explicit list of "known keys" is needed. But then you can as well
use a mapping (NSDictionary) from external element names to internal properties
to avoid any conflicts.
I think that you are confusing methods with properties, and you are making things more complicated that how they are.
Is enough that, given an elementName that contains directly the setter name (i.e.: setDate), you invoke the selector passing that argument the object argument:
SEL selectorName = NSSelectorFromString(elementName); // elementName something like "setDate"
if ([self.newsItem respondsToSelector:selectorName])
{
[self.newsItem performSelector: selectorName withObject: sanitisedElement];
}
As for the description method, it has overridden NSObject's description, so you have two choices: name it in another way, or leave it like it is, and invoke it on super when you need the object description, with the help of Objective-C runtime:
struct objc_super superclass= { self.newItem, [self.newItem superclass] };
NSString* desc= objc_msgSendSuper(&superclass, #selector(description));
You can always override inherited methods.
By creating a property whose getter is the same as the signature of An inherited method, you are overriding it.
Is it bad? Yes if your implementation is not useful for debugging.
As best practice for KVC and KVO purposes it is a good idea to avoid potentially clashing with common inherited methods properties and ivars.
The common approach to this is to make longer property and method names and to make them more likely to be unique. One common way is by prefixing all yours with an abbreviation common to your class or framework or code.
Using something commonly used by Apple is likely to bite you in a rare and hard to debug way.
It's especially a bad idea to do this when core data is involved.
Don't be reluctant to make things longer. Code completion will type for you. Plus, a nice side effect of class specific prefixing is pseudo not only the pseudo namespace but that your class specific properties, variables, constants and methods will bubble up first in code completion.

Semantic Issue: Property's synthesized getter follows Cocoa naming convention for returning 'owned' objects

I'm currently using the iOS 5 SDK trying to develop my app.
I'm trying to make an NSString a property, and then to synthesize it in the .m file (I have done this before with no issues). Now, I came across this: "Semantic Issue: Property's synthesized getter follows Cocoa naming convention for returning 'owned' objects."
This is my code:
.h
#interface ViewController : UIViewController {
NSString *newTitle;
}
#property (strong, nonatomic) NSString *newTitle;
.m
#synthesize newTitle;
Does anyone have a clue how I could fix this?
Thanks!!
My guess is that the compiler version you’re using follows the memory management rules for declared properties, too — more specifically, for declared properties’ accessors:
You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”.
A property named newTitle, when synthesised, yields a method called -newTitle, hence the warning/error. -newTitle is supposed to be a getter method for the newTitle property, however naming conventions state that a method whose name begins with new returns an object that’s owned by the caller, which is not the case of getter methods.
You can solve this by:
Renaming that property:
#property (strong, nonatomic) NSString *theNewTitle;
Keeping the property name and specifying a getter name that doesn’t begin with one of the special method name prefixes:
#property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
Keeping both the property name and the getter name, and telling the compiler that, even though the getter name starts with new, it belongs to the none method family as opposed to the new method family:
#ifndef __has_attribute
#define __has_attribute(x) 0 // Compatibility with non-clang compilers
#endif
#if __has_attribute(objc_method_family)
#define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
#else
#define BV_OBJC_METHOD_FAMILY_NONE
#endif
#interface ViewController : UIViewController
#property (strong, nonatomic) NSString *newTitle;
- (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
#end
Note that even though this solution allows you to keep newTitle as both the property name and the getter name, having a method called -newTitle that doesn’t return an object owned by the caller can be confusing for other people reading your code.
For the record, Apple have published Transitioning to ARC Release Notes, in which they state:
You cannot give a property a name that begins with new or copy.
They’ve already been notified that their statement is not quite accurate: the culprit is the getter method name, not the property name.
Edit 17 Jan 2015: I’ve just noticed a recent commit to Clang that suggests option 3 above (using objc_method_family(none)), including a fix-it, for the general case where a property name matches one of the special method family prefixes. Xcode will likely incorporate this change eventually.
Unacceptable Object Names
newButton
copyLabel
allocTitle
Acceptable Object Names
neueButton
mCopyLabel
_allocTitle
#arc #auto-synthesized #xcode-4.6.1
** EDIT **
Apparently you can't use mutableCopy either.
The name of the member starting with new is what triggers the warning. Change the name to editedTitle and the warning will go away. I was unable to find documentation confirming this but through testing was able to determine that member variables that begin with 'new' aggravate the compiler.
ARC does not allow to use "New...." in property name. but you can use "newTitle" by changing getter name.
#property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;
It doesn't look like what Bavarious was suggesting was what you wanted to do. All you want to do is declare an instance variable NewTitle and then synthesize the property. We used to have to declare the instance variable and property. No more.
Now, I believe the right way of doing this is the following:
.h
#interface ViewController : UIViewController
#property (nonatomic, strong) NSString *newTitle;
.m
#synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage
The instance variable for the property newTitle is synthesized. You don't want your instance variable to be the same as your property - too easy to make mistakes.
See Example: Declaring Properties and Synthesizing Accessors
In CoreData if you use "new..." in attribute (compile normally) it will crash randomly with a "bad access" exception.
There is no crash log and the line shown with the "All Exceptions Breakpoint" will not help you at all.
Writing a setter manually with the name same as the property's removed this warning.
NS_RETURNS_NOT_RETAINED is used to solve the naming problem.
#property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;
We can find its definition as follows:
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
The 'ns_returns_not_retained' attribute is the complement of 'ns_returns_retained'. Where a function or method may appear to obey the Cocoa conventions and return a retained Cocoa object, this attribute can be used to indicate that the object reference returned should not be considered as an "owning" reference being returned to the caller. The Foundation framework defines a macro NS_RETURNS_NOT_RETAINED that is functionally equivalent to the one shown below.
Besides the issue that you should/can't use "new" in front of you property names, let say one more thing: Try to avoid "new" in front of names in general. "New" is dependent on time. Currently it is new for you, but some time later you maybe want to implement something new again. So using "new" in names is always bad. Try to think this way: In the programming world, "new" is always creating something: a new instance of something.
In your case when you want to assign a different title then the current name your property titleReplacement.
One more thing: Try to name functions and methods with the verb first, like setSomething or getSomething.
But in properties try to name the object first, like heightMinimum, heightMaximum, etc. -> when you use your inspector when you are coding, you always looking for objects. Try it out. ;-)
try this:-
#property (nonatomic,retain) NSString *newTitle;

Where are the synthesized ivars stored?

I've been reading up on the automatically synthesized ivars. My question is, "WHere are automatically they allocated?" I would have expected them to be part of self, so that I could see them in the debugger, but it seems that the only way I can see them is by invoking the accessor method (via the gdb 'po' command). Isn't there space in the class/object's struct (as there would be for an explicitly declared ivar)?
(Is there a description of the in-memory representation for a modern Objective-C object?)
Being a C guy, it makes me very uncomfortable to not to be able to see where everything is. :-P
Looks like this will tell you:
How do automatic #synthesized ivars affect the *real* sizeof(MyClass)?
I am a C guy at heart too. Why bother using these auto generated ones? I like looking at a class and seeing what it holds onto in terms of data.
Interesting: Neat how they took the 64 bit change to make things better.
http://www.sealiesoftware.com/blog/archive/2009/01/27/objc_explain_Non-fragile_ivars.html
They are added to the objective-c object (which is a C structure) no different to a regular ivar, so for example:
#interface TestObject : NSObject {
}
#property (nonatomic, assign) int theInt;
#end
#implementation QuartzTestView
#synthesize theInt;
#end
You can refer to theInt ivar directly (not through property accessors) either:
- (void)someMethod {
theInt = 5;
}
OR
- (void)someOtherMethod {
self->theInt = 10;
}
See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html - using the modern runtime an instance variable "will be synthesized for you". It can be nice to add a variable yourself instead though (so that you can see it when debugging in self), however you have to be careful not to do direct assignments to the instance variable for retain or copy based properties.

#synthesize syntax when overriding accessors

I am doing a value object / Entity, that holds data for my model.
I get the data from a web service as JSON, now, instead of moving all the different objects from the parsed JSON over into different properties on my Entity. i.e. reading out the NSString for the #"name" key and setting it to [Entity setName:[JSONDictionary objectForKey:#"name"] etc. My Entity has one actual property,
NSDictionary *dataDictionary, this property hold the JSON dictionary as it left the parser.
Now when I need the name value I write an accessor that looks like this:
- (NSString*) name {
return [self.dataDictionary objectForKey:#"name"];
}
This is nice, I don't have to do any work unless there is a request for that particular property.
Now my question is how do I best tell the compiler that the accessor exists, but does not hold a "real" property.
I have this in my interface:
#property(nonatomic, retain) NSString *name;
And the #synthesize in my implementation, but this seems to create an overhead in my logic. Objective C will, as far as I understand, make a room in memory for me to store an object of type NSString when I do the #property(nonatomic, retain) and technically I don't need this as I am already storing this value in the the NSDictionary *dataDictionary
If I make it #dynamic I guess I would also have to provide a setter, which I would never need.
So, Is there a syntax that lets me create the illusion to all objects accessing the Entity that these are "normal" properties, but internally in the Entity not alloc/store unnecessary objects or write more code than is needed?
Declare a name method in your interface, not a property.
- (void)name;

Objective-C synthesize property name overriding

I am trying to understand the purpose of the synthesize directive with property name overriding. Say that I have an interface defined as follow:
#interface Dummy ... {
UILabel *_dummyLabel;
}
#property (retain, nonatomic) UILabel *dummyLabel;
And in the implementation file, I have:
#synthesize dummyLabel = _dummyLabel;
From what i understand, "dummyLabel" is just an alias of the instance variable "_dummyLabel". Is there any difference between self._dummyLabel and self.dummyLabel?
Yes. self._dummyLabel is undefined, however _dummyLabel is not.
Dot syntax expands out to simple method invocations, so it's not specific to properties. If you have a method called -(id)someObject, for example in the case of object.someObject, it will be as if you wrote [object someObject];.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Your understanding is incorrect. dummyLabel is the name of the property, and is not an alias for the instance variable - the instance variable is only called _dummyLabel. So the following holds for an instance of Dummy called myObject:
[myObject dummyLabel] works
myObject.dummyLabel works
[myObject _dummyLabel] fails
myObject._dummyLabel fails
myObject->dummyLabel fails
myObject->_dummyLabel depends on the visibility of the ivar (#public, #private, #protected)
[myObject valueForKey: #"dummyLabel"] works
[myObject valueForKey: #"_dummyLabel"] depends on the implementation of +accessInstanceVariablesDirectly (i.e. it will work in the default case where +accessInstanceVariablesDirectly returns YES).
The advantage of having another name
for the ivar than for the property is
that you can easily see in the code
when you are accessing one or the
other - Andre K
I'm not able to find a 'comment' button so I'm having to post as an 'answer'.
Just wanted to expand on Andre's comment - by knowing when you are using the synthesized properties vs the vanilla variable, you know (especially in case of setters) when a variable is being retained/copied/released automatically thanks to your nice setter, vs being manipulated by hand.
Of course if you are doing things right, you probably don't need the help of a setter to retain/release objects properly! But there can be other scenarios too where referring to your ivars as self.ivar instead of _ivar can be helpful, such as when you are using custom setters/getters instead of the default synthesized ones. Perhaps every time you modify a property, you also want to store it to NSUserDefaults. So you might have some code like this:
#interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
#property (nonatomic, assign) BOOL autoLoginOn;
#end
#implementation SOUserSettings
#synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:#"UserPrefAutoLoginOn"];
}
#end
Note: This is just illustrative code, there could be a thousand things wrong with it!
So now, in your code, if you have a line that says _autoLoginOn = YES - you know it's not going to be saved to NSUserDefaults, whereas if you use self.autoLoginOn = YES you know exactly what's going to happen.
The difference between _autoLoginOn and self.autoLoginOn is more than just semantic.
I don't see any big advantage of
renaming _dummyLabel to dummyLabel
In some ObjC runtimes you have a hard time making instance variables invisible to users of the class. For them sticking some prefix (or suffix) on your instance variables can make it clear (or more clear) that you don't want anyone messing with your variables. However you don't want that gunk on your public functions. This lets you get it off.
It could also be useful if you need to maintain an old interface with one set of names at the same time as a new set of APIs with a new set of names (setLastname vs. setSurname).
Old post, but I think its important to mention, that it is recommended to access variables via getters and setters (so, with dot notation). Accessing a field directly (_ivar) is strongly recommended only when initializing it.
There is some good Apple's article:
https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
Last paragraph:
You should always access the instance variables directly from within
an initialization method because at the time a property is set, the
rest of the object may not yet be completely initialized. Even if you
don’t provide custom accessor methods or know of any side effects from
within your own class, a future subclass may very well override the
behavior.