What is the point of calling "#synthesize slider = _slider;" - ios

Can someone explain to me the significance of creating (what seems to be) an extra variable and why put an underscore before a new variable with the same name as the last.
I have read that it is to do with creating instance variables but why would you want to create a UI element as an instance variable? Can you please provide a use case?
This objective c code for use in iOS development.
Thanks.

When you #synthesize a property and you do not provide your own getter and setter methods (in which case there is no need to #synthesize) then there is always a new instance variable created. By default it gets the same name as the property. So #synthesize slider; makes an instance variable named slider behind the scenes.
The problem here is that you might mistakenly type slider = xxx when you really meant to use self.slider = xxx. When you make something a property, best practice says you should always access it through self.propertyName (except in your init and dealloc methods and any custom getter and setter methods).
So in order to avoid this, the #synthesize statement is used to rename the backing ivar into something that is harder to confuse with the property. If you now use slider instead of self.slider the compiler will give an error message because slider is no longer the name of an instance variable.

The reason for doing that is to make the instance variable clearly stand out from the property dotting syntax. It also has the practical effect of avoiding shadowing of instance variables from argument names, which also occur in some situations.
The reason for using an instance variable at all is in most cases to avoid KVO triggering in dealloc. If you do this, you risk triggering KVO in such a way that your observers gets a deallocated object passed to them, causing an EXC_BAD_ACCESS.
- (void)dealloc
{
self.slider = nil;
[super dealloc];
}
So it's common to do this instead, which will not trigger KVO since you don't do property access.
- (void)dealloc
{
[_slider release];
[super dealloc];
}

This is commonly used to synthesize the property to a private prefixed or suffixed ivar. It tries to prevent you from accidentally accessing the ivar and not the property or overriding the ivar with a method argument.
Consider this:
#implementation MYClass
#synthesize flag = flag_;
- (void)doSomethingWithFlag:(BOOL)flag {
if (flag) {
// You do not need to worry about confusing the ivar
// flag and the param flag because it is synthesized to flag_
}
}
- (void)doSomething {
if (flag) { // Doesn't work -> use accessor self.flag
...
}
}
#end

Related

Specifying only getter generates warning b/c no setter, but setter won't compile

I believe the image is pretty descriptive of my problem. If I define only a custom getter as below:
- (UIImage *) secondaryIconImage {
if (_secondaryIconImage) return _secondaryIconImage;
return nil;
}
then I get an error: 'cannot pair a synthesized setter with a user defined getter'. However, if I try to declare the setter as well my code won't compile at all:
- (void) setSecondaryIconImage:(UIImage *)secondaryIconImageVar {
_secondaryIconImage = secondaryIconImageVar;
}
In particular this gives me the compile time error 'Use of undeclared identifier _secondaryIconImage'
I thought perhaps once I declared the setter I would have to synthesize the instance variable myself, so I tried adding:
#synthesize _secondaryIconImage;
This didn't help. What's going on here and how can I fix it?
p.s. I have a custom getter because I will eventually need to do something fancier, but I didn't see a reason to complicate the example since even this basic example is giving me a problem.
As it notes, you cannot define the getter without the setter. (Your getter makes no sense of course, so I assume your actual getter is more complex?)
If you define the getter and the setter, nothing will be synthesized for you (since you've written everything, there's nothing to synthesize), and no ivar will be defined for you. You need to define it yourself if you need it.
You need to explicitly request an ivar via your #synthesize (thanks to Richard Ross for setting me straight):
#synthesize secondaryIconImage = _secondaryIconImage;
Your code asks for a property called _secondaryIconImage, so the ivar would be __secondaryIconImage.

Why init.. methods are required in Objective C?

Wherever I've read, it's written to never use an object without calling it's initializer function. And initializer functions always "have to" start with "init".
Is there a reason behind this naming (Does naming a method starting with init do something special)? What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
Alloc is called to allocate space in memory for the data type you are specifying. Whether it is NSString or NSNumber, calling Alloc will reserve the most efficient space in memory as possible for that data type (small or large).
Init is called to instantiate the class and superclass's important variables. These variables could include the Rect to recalculate a certain size in order to layout subviews, or perhaps instantiate with a delegate of some kind to perform some protocol upon creation. If it all becomes too much for you Objective-C does allow you to instantiate objects like MyClass *myObject = [MyClass new];
It may all seem redundant and a waste of time, but fortunately Swift has cut down tremendous amounts of redundancies like this in the new programming language. Now all you have to do is var myObject = MyClass() and if there are any custom initializers they would likely be writen like so var myObject = MyClass(frame: CGRectZero)
Happy coding!
I recommend reading the Apple Documentation on Object Initialization, and Initialization.
Is there a reason behind this naming (Does naming a method starting with init do something special)?
It is the convention, beginning a method name with init does not do anything special.
There are some minor quirks, such as if a method beginning with init returns type id, the compiler will convert the return type to instancetype, but these are barely worth mentioning.
What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
If you're using a standard SDK class, you'll likely run into a crash / exception. Initialization is used to set up the initial state of the instance variables, and without doing this can lead to undefined behaviour.
For a small example, if you called [[MyObject alloc] vegetable]; with the following class, you'd get nil returned because _vegetable hasn't been assigned.
#interface MyObject : NSObject
-(NSString*)vegetable;
#end
#implementation MyObject {
NSString *_vegetable;
}
-(instancetype)init {
self = [super init];
if (self) {
_vegetable = #"Cabbage";
}
return self;
}
-(NSString*)vegetable {
return _vegetable;
}
#end
It is the way you create objects in Objective-C. It is a hard requirement of the language. Creating an object in Objective-C is a 2 step process: alloc and init.
Under the covers, the reason you must call init is, wait for it, initialization.
The call to alloc creates a block of memory for your object and zeros it out. Calling init allows the object and it's ancestors to set things up so the object is ready to function. It initializes the object's memory and does other housekeeping that set the object up.
Further, every object's init method needs to call super init, so the initialization goes all the way up the object chain, all the way to NSObject. All the ancestor classes are designed to assume that their init method is called.

Is setting a retained property to nil enough?

I see some code with
#property (nonatomic, readwrite, retain) id something;
And they synthesise it:
#synthesize something = something_;
And in the constructor:
self.something = #"HELLO!";
I assume that, the above line effectively retains that string.
But then, in their dealloc method, they do this:
[self setSomething:nil];
I guess that it is fine, because I imagine that when you set a property to nil, the old value is released. But then, I noticed that all the other classes they did had something like
[something release];
Instead, so I'm no longer sure. Are both ways correct?
Short answer: Use ARC. It takes care of this stuff for you. It's much less error-prone, and just as fast as manual reference counting.
Longer answer:
If you use retained properties, then yes, setting the property to nil is the correct thing to do.
like this:
self.something = nil;
That works because the setter for a retained property first releases the old value, then retains the new value and assigns it to the property's iVar. Since the new value is nil the retain does nothing.
If in your second example:
[something release];
something is the iVar for a property, this code will cause a future crash if it is called from anywhere but in the code for the object's dealloc method. The reason is that this releases the object, but does not zero out the iVar. Later, when the object that has a something property is released, its dealloc method fires. The code in the dealloc method should attempt to release the object's retained properties. Sending release to an object that was already deallocated causes a crash.
In your case, you are asking about the code in a dealloc method. In dealloc, calling [something release] and setting the property to nil have the same result of releasing the object. Invoking the setter is probably safer, though, since custom setters sometimes have other code with additional "side effects." Since you're writing the dealloc method, you should be the author of the class, and should be aware of any special code in the setter method.
Now, if something is an instance variable, not a property, the correct thing to do is
[something release]
something = nil;
EDITED 5 June 2014 to discuss the case of code in a dealloc method.
Better to use [something_ release]. This won't cause setter to be called, which otherwise could cause some actions to be performed that are undesired in dealloc.
Both are correct, [self setSomething:nil]; will be better, when something is released to 0 retainCount then dealloc. This prevent using something from crash with BAD_EXE.
As mifki said, setter to be called if use [self setSomething:nil]; so this is depended on what have you done in setter method, a good setter should care about set value to nil, and deal with the case properly, and will not be undesired.
And even if setter method implement can't be cared to set to nil always, the better release style should be :
[something_ release], something_ = nil; //this should be safely release always

Need assistance regarding Objective-c properties concept

I am reading Apple Doc for understanding property instance variable but bit confused
From Apple Doc:
Most Properties Are Backed by Instance Variables By default, a
readwrite property will be backed by an instance variable, which will
again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for
the life of the object. The memory used for instance variables is
allocated when the object is first created (through alloc), and freed
when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has
the same name as the property, but with an underscore prefix. For a
property called firstName, for example, the synthesized instance
variable will be called _firstName.
Although it’s best practice for an object to access its own properties
using accessor methods or dot syntax, it’s possible to access the
instance variable directly from any of the instance methods in a class
implementation. The underscore prefix makes it clear that you’re
accessing an instance variable rather than, for example, a local
variable:
If using accessor methods or dot syntax is best practice then why user _ivarPropertyName?
Why use ivar for presenting properties? what are its benefits? when apple says "using accessor methods or dot syntax is best practice"
#property declares the existence of a property (describing its interface), but doesn't specify the implementation of that property. But properties need to store their contents somewhere. By default, the compiler synthesizes an ivar for that (and matching setters and getters). So normally you can ignore the existence of the ivar and just use dot syntax.
I follow Apple's advice and try to avoid using ivars directly. But somtimes you want to access a property without invoking its getter. The most common exception in my code is lazily-initialized read-only properties:
#interface MyObject : NSObject
#property ( nonatomic, readonly ) id someProperty ;
#end
#implementation MyObject
#synthesize someProperty = _someProperty ; // required; compiler will not auto-synthesize ivars for readonly properties
-(id)someProperty
{
if ( !_someProperty )
{
_someProperty = ... create property here
}
return _someProperty ;
}
#end
Also, you may not want to invoke the getter for a property in your -dealloc method... for example, a timer property. To avoid creating a timer in -dealloc, access the ivar directly:
-(void)dealloc
{
[ _myTimer invalidate ] ; // don't use self.myTimer here, that would create a timer even though we're going away...
}
There are probably more use cases. For most properties you don't even need to use the ivar, just use <value> = self.property and self.property = <new value>.
edit:
Also, there will be some additional overhead for accessing the property via message dispatch (using dot-accessor syntax or the getter) vs directly accessing the ivar, but it will make no difference in almost all cases.

how to forbid the basic init method in a NSObject

I want to force user to use my own init method (for example -(id)initWithString:(NSString*)foo;) and not the basic [[myObject alloc]init];.
how can I do that?
All other answers here are outdated. There is a way to do this properly now!
While it is easy to just crash at runtime when somebody calls your method, compile-time checking would be far preferable.
Fortunately, this has been possible in Objective-C for a while.
Using LLVM, you can declare any method as unavailable in a class like so
- (void)aMethod __attribute__((unavailable("This method is not available")));
This will make the compiler complain when trying to call aMethod. Great!
Since - (id)init is just an ordinary method, you can prohibit calling of the default (or any other) initializer in this way.
Note, though, that this will not insure against the method being called using the dynamic aspects of the language, for instance via [object performSelector:#selector(aMethod)] etc. In the case of init, you won't even get a warning, because the init method is defined in other classes, and the compiler doesn't know enough to give you an undeclared selector warning.
So, to ensure against this, make sure that the init method crashes when being called (see Adam's answer).
If you want to disallow - (id)init in a framework, make sure to also disallow + (id)new, as this will just forward to init.
Javi Soto has written a small macro to forbid using the designated initializer faster and easier and to give nicer messages. You can find it here.
tl; dr
Swift:
private init() {}
Since all Swift classes include an internal init by default, you can change it to private to keep other classes from calling it.
Objective C:
Put this in your class's .h file.
- (instancetype)init NS_UNAVAILABLE;
This relies on an OS define that prevents the method named from being called.
The accepted answer is incorrect - you CAN do this, and it's very easy, you just have to be a bit explicit. Here's an example:
You have a class named "DontAllowInit" which you want to prevent people init'ing:
#implementation DontAllowInit
- (id)init
{
if( [self class] == [DontAllowInit class])
{
NSAssert(false, #"You cannot init this class directly. Instead, use a subclass e.g. AcceptableSubclass");
self = nil; // as per #uranusjr's answer, should assign to self before returning
}
else
self = [super init];
return nil;
}
Explanation:
When you call [super init], the class that was alloc'd was the SUBCLASS.
"self" is the instance - i.e. the thing that was init'd
"[self class]" is the class that was instantiated - which will be SUBCLASS when the SUBCLASS is calling [super init], or will be the SUPERCLASS when the SUPERCLASS is being called with plain [[SuperClass alloc] init]
So, when the superclass receives an "init" call, it just needs to check whether the alloc'd class is the same as its own class
Works perfectly. NB: I don't recommend this technique for "normal apps" because usually you INSTEAD want to use a Protocol.
HOWEVER ... when writing Libraries ... this technique is VERY valuable: you frequently want to "save (other developers) from themselves", and its easy to NSAssert and tell them "Oops! you tried to alloc/init the wrong class! Try class X instead...".
-(id) init
{
#throw [NSException exceptionWithName: #"MyExceptionName"
reason: #"-init is not allowed, use -initWithString: instead"
userInfo: nil];
}
-(id) initWithString: (NSString*) foo
{
self = [super init]; // OK because it calls NSObject's init, not yours
// etc
Throwing the exception is justified if you document that -init is not allowed and therefore using it is a programmer error. However, a better answer would be to make -init invoke -initWtihString: with some suitable default value i.e.
-(id) init
{
return [self initWithString: #""];
}
Short answer: you can't.
Longer answer: the best practice is to set your most detailed initializer as the designated initializer, as described here. 'init' will then call that initializer with sane, default values.
Another option is to 'assert(0)' or crash in another way inside the 'init', but this isn't a good solution.
I actually voted up Adam's answer, but would like to add some things to it.
First, it is strongly encouraged (as seem in auto-generated init methods in NSObject subclasses) that you check self against nil in inits. Also, I don't think class objects are guaranteed to be "equal" as in ==. I do this more like
- (id)init
{
NSAssert(NO, #"You are doing it wrong.");
self = [super init];
if ([self isKindOfClass:[InitNotAllowedClass class]])
self = nil;
return self;
}
Note that I use isKindOfClass: instead because IMHO if this class disallows init, it should disallow its descendants to have it as well. If one of its subclass want it back (which doesn't make sense for me), it should override it explicitly by calling my designated initializer.
But more importantly, whether you take the above approach or not, you should always have appropriate documentation. You should always clearly state which method is your designated initializer, try as best as you can to remind others not to use inappropriate initializers in documentation, and put some faith in other users/developers, instead of trying to "save everybody else's asses" with clever codes.

Resources