Does the name of an argument matter when defining a function? - objective-c

Does it matter if I define a function with one argument name in the .h file, for example...
-(foo *) initWithId:(NSString *)id;
And then in my implementation give the argument a different name because it hides a class property:
-(foo *) initWithID:(NSString *)idString;
I know that the autocomplete files use .h as the 'basis' for their autocomplete fillers, and while it doesn't apply to this scenario, I prefer to use the property name in my functions to remain as consistent in my coding style as possible. It makes more sense to understand that getFoo and setFoo both apply to the same property 'foo' as in -(bar *) initWithFoo:(id) foo;.
As far as I can tell, the compiler doesn't have any issues with it, but somehow it seems like it SHOULD matter.

The LLVM analyzer in Xcode does seem to care about some things like methods starting with new and copy.
Here's a sample warning when I name a property starting with new:
"Property's synthesized getter follows Cocoa naming convention for
returning 'owned' objects"
(the #property had a #synthesize that created a getter method starting with new).

No, the compiler doesn't care. Other people who read your code might care.

the only time it really matters is if you have an instance variable name with the same name.
#synthesize something;
- (void)methodForSomething:(id)something
{
something = something;
}
this will throw an error. obviously the solution is to modify your instance variables naming.
#synthesize something = _something;
other then that, parameter names dont matter.

Related

Is it OK to have a method's variable with the same name as a declared property?

I understand this is probably bad practice, but I was just curious as to whether or not this has any negative side-effects, in Objective-C (trying to learn as much as I can):
#interface MyClass ()
// Declare a string called 'foo'
#property (nonatomic, strong) NSString *foo
#end
#implementation MyClass
...
- (void)modifyFoo {
// Create a local variable with the same name as a property
NSString *foo = #"Hello!" // No compiler warnings?
self.foo = foo; // <---- Is this OK?
}
This will not throw up a warning in the compiler, and sure enough, my code works as normal. If there are zero negative side-effects, does the type of property, e.g. weak/strong/assign, etc, have an influence on whether or not this is OK?
Note: I am aware that this will not work when the property is synthesised.
This is fine and is my personally preferred approach. The reason no compiler warning is generated is that the instance variable is actually named _foo. This is done by the auto-synthesise added by the compiler (it generates #synthesize foo = _foo for you). Maintaining naming consistency aids clarity.
The main potential side effect is that you inadvertently add / fail to add self. and end up trying to message nil.
Firstly:
this will not work when the property is synthesised.
Huh? Why not?
Actually, it's "OK" in the sense that it works. Actually, there's no ambiguity when you use the self keyword and the dot notation to access your property. If, however, you had an instance variable with the same name as your local variable, then the object with a narrower scope (the local variable in this case) hides the one with a wider scope (the ivar). And that may be undesirable. As far as I know, it even results in a compiler warning. Furthermore, it's hard to get it wrong and decreases overall code readability, so don't do this if you have that identically named instance variable.
If I recall correctly, recent versions of the clang/LLVM toolchain automatically synthesize properties for you, and the name of the backing ivar for a property is preceded by a leading underscore, so this should not be a problem.

About naming the instance variable in Objective C

Sometimes we may explicitly specify the name of an instance variable in the synthesize statement, e.g.,
In SomeViewController.h,
//....
#property (nonatomic, retain) NSObject *variable;
//....
In SomeViewController.m,
//....
#synthesize variable = _variable;
//....
But why bother making this extra effort if the instance variable will be implicitly named as _variable even if we simply put it as:
#synthesize variable;
in the SomeViewController.m.
Can anyone share some idea on why it is necessary? Thank you :D
Just to avoid confusion (see comments): Using the = _variable part of the #synthesize is not required, nor is the #synthesize itself required any more.
This effort is only requied, when you want to link the property to a specific instance variable. With earlier Objective-C versions this part of the statement was required to set the name to something different from the property name, so when you want to call the iVar _variable and the property variable. The default would be variable (unlike your question). Without that = something ivar and property have the same name.
BTW, there is nothing wrong with using the same name for both. But having different names, a leading _ would do, makes it more clear to the programmer whether he/she accesses the ivar directly or though the accessor methods. Sometimes this is of vast importance, especially when not using ARC. Therefore it helps avoiding errors.
With current Objective-C, however, you could omit the #synthesize statement at all and go with the defaults in that case. The default automatically synthesized instance variable name would have a leading _ so _variable in your example.

Why does Xcode automatically create variables with underscores?

Why in the newest version of Xcode (dp-4) are variables declared with retain,nonatomic made to use the underscore before the variable name? Does this create some sort of type safety?
For example, I create a property:
#property (retain, nonatomic) IBOutlet UILabel *name;
Unless I change the variable inside the dealloc to not have the _, I have to do:
#synthesize name = _name;
Why is this?
Mark Dalrymple, who's way smarter than I am, wrote a blog post at Big Nerd Ranch about this very subject. Bottom line: the underscore is a good idea. I will summarize his post here just in case the link stops working in the future, but if possible you should read his post instead of my summary.
He wrote this post back when explicitly calling #synthesize was mandatory. He advocated code such as:
// soapbubble.m
#synthesize viscosity = _viscosity;
#synthesize detergentBrand = _detergentBrand;
These days Xcode automatically and implicitly includes #synthesize. And it does so using the prepended underscore so apparently Apple's engineers agree with Mark.
His first reason is stylistic. It allows you to easily see which variables are local and which are arguments in a setter:
- (void) setPonyName: (NSString *) ponyName {
[_ponyName autorelease];
_ponyName = [ponyName copy];
}
(This is a pre-ARC setter, so now this method would be completely unnecessary, but if the setter did anything more involved than simply releasing and assigning a value it would still apply.)
His second reason (and the one I think is more important) is that eliminates a certain class of bug that can be very difficult to track down.
This code:
self.ponyName = #"Mikey";
is identical to:
[self setPonyName: #"Mikey"];
Without the prepended underscore, this code is also valid:
ponyName = #"Mikey";
but it doesn't call the setter so any side effects in the setter don't occur. Again, in a situation where the setter does extra work besides changing the local variable's value this can cause big headaches. With the prepended underscore, that line would cause a compile error. You would have to be very explicit about wanting to set a local variable:
_ponyName = #"Mikey";
and, being the conscientious programmer you are, you would include a comment explaining exactly why you are performing this irregular maneuver.
"_name" in your #synthesize name = _name, is just a variable name created automatically by your Xcode. This is done because #synthesize just creates setters and getters and if you don't use _name, it'll take your property name, i.e. name (in this case) and finally leads to bugs in your app. _name is just a naming convention. You can use any variable name in place of _name. So that #synthesize will use that variable name in its implementation.

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.