Naming of formal parameters in setters with synthesized properties [duplicate] - objective-c

This question already has answers here:
Good practice for disambiguating argument names versus instance variable names in Objective-C
(3 answers)
Closed 9 years ago.
I have been learning and using Objective-C for quite some time now (it also kind of was my first OOP language) and I finally would like to know how to correctly name synthesized properties.
Let's take the following scenario:
I have got a property called someVariable.
#property (nonatomic, retain) NSString *someVariable;
and synthesize it
#synthesize someVariable;
How would the custom setter look like conventionally ?
1)
I would go ahead and say something like
-(void)setSomeVariable:(NSString *)someVar{
//input parameter MAY sound/look foreign due to the difference to the property
someVariable = someVar;
}
2) (illegal)
But I would like to name the formal parameter just like the property for the sake of readability and convenience. More like in Java like this:
-(void)setSomeVariable:(NSString *)someVariable{
//obviously illegal because this would call the setter over and over again
self.someVariable = someVariable;
}
3) (unconventional)
and according to what I have been reading in the past this
#synthesize someVariable = _someVariable;
is said to be unconventional and not supposed to be used.
So, am I correct in concluding that the way I have been doing it until now, is the only way to create a custom setter ?

3) is not unconventional, it's exactly what the compiler does if you don't provide the #synthesize statement.
This means that, without the #synthesize statement and the ivar declaration, you have an implicit ivar named _someVariable, and a custom setter would usually have a parameter named someVariable
-(void)setSomeVariable:(NSString *)someVariable {
_someVariable = someVariable;
}
Also note that providing custom setter and getter methods for a particular property indicates to the Xcode compiler to not provide the implicit ivar (here _someVariable). In the case of readonly properties, the same if true if you provide just the getter method.
WWDC 2012 session 405 provides a lot of details around Objective-C constructs for modern versions of the compiler.
EDIT
As H2CO3 has suggested in his answer, the code I wrote assumes you're using ARC. If you are using MRC, the setter method would rather be :
-(void)setSomeVariable:(NSString *)someVariable {
[someVariable retain];
[_someVariable release];
_someVariable = someVariable;
}

Related

What are the circumstances that cause a #property to not automatically create an instance variable? [duplicate]

This question already has answers here:
Under what conditions is #synthesize automatic in Objective-c?
(5 answers)
Closed 7 years ago.
I've only been in the Objective-C & Cocoa world for a year, so I wasn't around when properties weren't automatically synthesized
Whenever I create new classes in our project, I can declare #property BOOL testFlag without declaring an instance variable. Then, in the implementation, I could either call self.testFlag, [self testFlag], [self setTestFlag:NO]. But, I could also call _testFlag. I always assumed because properties are automatically synthesized with instance variables, that's why I can just append a "_" underscore before the property name to directly access the instance variable.
However, I have been refactoring really old files, that clearly were created before auto-synthesizing was a thing
So now in the header, I'd see something like this:
#interface testClass
{
BOOL _testFlag
}
#property BOOL testFlag;
In the implementation, there could be a custom setter/getter:
#implementation testClass
#synthesize testFlag = _testFlag;
-(void)setTestFlag:(BOOL)testFlag
{
_testFlag = testFlag;
}
-(BOOL)testFlag
{
return _testFlag;
}
But I thought because of auto-synthesizing, I could remove the _testFlag declaration in the header, and I could remove the #synthesize in the implementation. But when I do this, there are just a truck ton of errors; wherever somebody was directly trying to access the ivar _testFlag. (This actually includes the custom getter/setter above ^^, too)
Is there perhaps something I am missing with the project settings that prevent this old file from generating an implied instance variable for properties?
Remove the getter and setter to have automatic synthesis of the backing variable. When you supply both for the property, the assumption is that you're going to look after storage yourself.

How to prevent a variable from being created for a non-physical property in Objective-C? [duplicate]

This question already has answers here:
Declaring a property with no instance variable
(2 answers)
Closed 9 years ago.
In modern versions of Xcode, variables are automatically created to back properties. For example, #property (nonatomic, assign) BOOL isOpen would automatically create BOOL _isOpen. Is there a way to prevent such variables from being created when the property is meant to be non-physical? In the following example of a non-physical isOpen property, _isOpen is not needed. It is actually detrimental, because I've had co-workers inadvertdently use _isOpen and wonder why nothing would happen.
- (void) setIsOpen:(BOOL)isOpen
{
if (isOpen) {
[self.specialView open]
} else {
[self.specialView close];
}
}
- (BOOL) isOpen
{
return self.specialView.alpha > 0.0;
}
If you implement both the setter & the getter the variable will not be created. From Apple's docs:
The compiler will automatically synthesize an instance variable in all situations where it’s also synthesizing at least one accessor method. If you implement both a getter and a setter for a readwrite property, or a getter for a readonly property, the compiler will assume that you are taking control over the property implementation and won’t synthesize an instance variable automatically.
Your co-workers should not be able to reference _isOpen at all. I've checked your code in Xcode 4.6.3 and it behaves as per spec - no variable is created.
You need to specify both the getter and the setter. Assuming you do that, no instance variable is created.
Note that you can specify a different name for the getter, too. For boolean properties, the is prefix is usually dropped, though in the case of "open" I might leave it. I think it's clearer with the prefix.
For other boolean properties, though, something like this might be preferred:
#property (nonatomic, assign, getter=isOpen) BOOL open;
Then:
implement setOpen and isOpen.
read using BOOL value = object.open or BOOL value = [object isOpen]
write using object.open = value or [object setOpen:value].
Using #dynamic is not necessary; the recent compiler will detect you've specified both the getter and setter. #synthesize should not be necessary either. (There are a few edge cases; if you run into a case where it is necessary, by all means use it there).
Note, however, that I'm talking about the modern runtime here. 32-bit OSX targets use the legacy runtime, which has different rules.

Why do #synthesize variable names begin with an _? [duplicate]

This question already has answers here:
What does #synthesize window=_window do?
(3 answers)
Closed 9 years ago.
I'm just starting to use Objective-C and I need to clarify something
When I #synthesize a #property, it is common convention to do the following:
#interface Class : ParentClass
#property propertyName
#end
#implementation
#synthesize propertyName = _propertyName;
#end
I've seen plenty of questions and answers suggesting that "_propertyName" is widely accepted as the "correct" way to synthesize properties. However, does it serve ANY purpose? Or is it merely to increase readability and identify instance variables?
It makes it so that if you accidentally leave off "self." you get a nice compiler error instead of silently not having your methods called.
From http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
You Can Customize Synthesized Instance Variable Names
As mentioned earlier, the default behavior for a writeable property is
to use an instance variable called _propertyName.
If you wish to use a different name for the instance variable, you
need to direct the compiler to synthesize the variable using the
following syntax in your implementation:
#implementation YourClass #synthesize propertyName =
instanceVariableName; ... #end
Also:
Note: The compiler will automatically synthesize an instance variable
in all situations where it’s also synthesizing at least one accessor
method. If you implement both a getter and a setter for a readwrite
property, or a getter for a readonly property, the compiler will
assume that you are taking control over the property implementation
and won’t synthesize an instance variable automatically. If you still
need an instance variable, you’ll need to request that one be
synthesized: #synthesize property = _property;
By doing this the generated accessor actually got to know which variable(iVar) to use.
Yea, It increases the readability & also separates the private & public variables to understand & use. Private variable of Class generally written in "propertyName" format.You can say it is a coding convention where Private Variable Names use '' as prefix and Public Variables or Property Names are lowerCamelCase.

recursive issue with getter ios objective c

I have this property:
#property (nonatomic, getter = getSolutionsCount, setter = setSolutionsCount:) NSInteger solutionsCount;
and implementation
- (NSInteger)getSolutionsCount {
return self.solutionsCount;
}
and I get EXC_BAD_ACCESS on this method - (NSInteger)getSolutionsCount.
What am I doing wrong here?
dot syntax is basically a shortcut for calling the getter. You have infinite recursion in your getter method.
What you need to do is return the instance variable directly:
- (NSInteger)getSolutionsCount {
//latest xcode makes variables with _property name automatically
return _solutionsCount;
//older versions of xcode or having written #synthesize solutionsCount
//will necessitate
//return solutionsCount;
}
Also just FYI objective-c convention is to have the getter method be defined as just the variable name. A getter which is the same as the property name is assumed if you don't write a getter in the property declaration
EDIT:
also i'm assuming this isnt the whole implementation for your getter because if it is let the compiler make it for you automatically, you don't need to write anything. (or by writing #synthesize propertyName = _propertyName in your implementation block with older versions of xCode)
The line self.solutionsCount is translated to [self getSolutionCount]. You are making a recursive call.
If you simply want to return the synthesized ivar then don't even implement this method. But if you do then simply call return _solutionCount;.
The problem is that self.solutionsCount is identical to [self getSolutionsCount], so your getter is directly recursive. You probably want to access the underlying ivar directly, to do so use self->_solutionsCount. Or, if you prefer not to explicitly use self, simply _solutionsCount.
There are several problems here:
According to the naming convention getters should not start with get. To read the value you need to use self.solutionsCount. Hence, you do not need to specify the name of the getter method in the property declaration.
You do not need to specify the name of the setter for it will be automatically generated.
The property should look like this:
#property (nonatomic, assign) NSInteger solutionsCount;
You do not need to write a custom getter implementation to make it work. Ask the compiler to synthesize the methods for you:
#synthesize solutionsCount;
If you want to have a direct access to the instance variable, ask compiler to sythesize it for you:
#synthesize solutionsCount = _solutionsCount;
Read objective-c and naming convention docs first. They will help enormously.
Good luck!

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.