Difference between #interface declaration and #property declaration - objective-c

I'm new to C, new to objective C. For an iPhone subclass, Im declaring variables I want to be visible to all methods in a class into the #interface class definition eg
#interface myclass : UIImageView {
int aVar;
}
and then I declare it again as
#property int aVar;
And then later I
#synthesize aVar;
Can you help me understand the purpose of three steps? Am I doing something unnecessary?
Thanks.

Here, you're declaring an instance variable named aVar:
#interface myclass : UIImageView {
int aVar;
}
You can now use this variable within your class:
aVar = 42;
NSLog(#"The Answer is %i.", aVar);
However, instance variables are private in Objective-C. What if you need other classes to be able to access and/or change aVar? Since methods are public in Objective-C, the answer is to write an accessor (getter) method that returns aVar and a mutator (setter) method that sets aVar:
// In header (.h) file
- (int)aVar;
- (void)setAVar:(int)newAVar;
// In implementation (.m) file
- (int)aVar {
return aVar;
}
- (void)setAVar:(int)newAVar {
if (aVar != newAVar) {
aVar = newAVar;
}
}
Now other classes can get and set aVar via:
[myclass aVar];
[myclass setAVar:24];
Writing these accessor and mutator methods can get quite tedious, so in Objective-C 2.0, Apple simplified it for us. We can now write:
// In header (.h) file
#property (nonatomic, assign) int aVar;
// In implementation (.m) file
#synthesize aVar;
...and the accessor/mutator methods will be automatically generated for us.
To sum up:
int aVar; declares an instance variable aVar
#property (nonatomic, assign) int aVar; declares the accessor and mutator methods for aVar
#synthesize aVar; implements the accessor and mutator methods for aVar

This declares an instance variable in your object:
#interface myclass : UIImageView {
int aVar;
}
Instance variables are private implementation details of your class.
If you want other objects to be able to read or set the value of the instance variable (ivar), you can declare it as a property:
#property int aVar;
This means that the compiler expects to see setter and getter accessor methods for the property.
When you use the #synthesize keyword, you are asking the compiler to automatically generate setter and getter accessor methods for you.
So, in this case the compiler will generate code similar to this when it encounters the #synthesize keyword:
- (int) aVar
{
return aVar;
}
- (void)setAVar:(int)someInt
{
aVar = someInt;
}
By default on the iPhone (and on the 32-bit runtime on the Mac), #synthesize requires an instance variable to be present in order to store the property's value. This ivar is usually named the same as the property, but doesn't have to be, for instance you could do this:
#interface myclass : UIImageView {
int aVar;
}
#property int someValue;
#synthesize someValue = aVar;
Neither #synthesize nor #property are actually required, you can create your own getter and setter methods, and as long as you create them using Key-Value Coding-compliant syntax, the property will still be usable.
The requirement for an ivar to be present as well as the #property declaration is due to the fragile base class limitation of the 32-bit Objective-C runtime on both the Mac and iPhone. With the 64-bit runtime on the Mac you don't need an ivar, #synthesize generates one for you.
Note that there are numerous keywords you can use with your #property declaration to control what sort of synthesized accessor code is created, such as readonly for a getter-only accessor, copy, atomic, nonatomic and so on. More information is in the Objective-C 2.0 Programming Language documentation.

Classes can have instance variables (ivars). These are in the first section, and are only visible to code in that class, not any outside code. I like to prefix them with an underscore to show their internal-ness. In low level terms, the ivars are added as an additional member to the struct that the class you are creating uses internally.
The second declaration, #property, is a declared property. It is not required (except when you are using #synthesize), but it helps other programmers (and the compiler!) know that you are dealing with a property, and not just two methods -setAVar and -aVar, which is the alternative way of doing this.
Thirdly, the #synthesize actually creates the methods to set and access the property from outside the class. You can replace this with your own setter and getter methods, but only do that if you need to, as the built-in ones have some features that you would otherwise have to code yourself. In fact, using the #synthesize aVar = _someVariable; syntax, you can have your property actually reference a differently named instance variable!
Short version:
The #property is just a hint to the compiler and other programmers that you are making a property and not just getter/setter methods. The instance variables are internal to the class, and otherwise cannot be normally accessed from outside it. The #synthesize just creates simple getters and setters for you, to go with your #property, but you can also just code those getters and setters yourself, like any other method.

Class A
#interface myclass : UIImageView {
int aVar;
}
If you declare like this then you can only use this variable within your class A.
But suppose in Class B
A *object=[A new];
object.aVar---->not available
For this you should **declare aVar as a property in Class A**
so class A should look like
Class A
#interface myclass : UIImageView {
int aVar;
}
#property int iVar;
and
.m file
#synthesize iVar;
So now you can use this iVar in another class Suppose B
Class B
#import "Class A.h"
enter code here
A *object=[A new];
object.aVar---->available
means
object.aVar=10;

#interface declares the instances variables of a class in obj-c. You need it to create an instance variable. However the variable is not visible outside the class by default (as the field is by default protected).
#property tells the compiler to specify a particular property accessor (get/set) method. However, you will need to use #synthesize to actually have the compiler generate the simple accessors automatically, otherwise you are expected to create them on your own.

I recently started learning iphone apps. As per my knowledge #property is used in .h file as a setter method and #synthesize in .m file as getter method. In Java we use setter and getter methods, same as Java, in Objective C we use #property and #synthesize.
Please forgive me If u think I mislead you.

Related

Controlling access to instance variables in Objective-C

From all code I've seen, almost always is used something like this for property scope definition:
Class extension
/*We declare the class extension*/
#interface MyClass ()
#property (nonatomic, retain) Type *aPrivateProperty;
- (void)aPrivateMethod;
#end
/*
We can use the main implementation block to implement our properties
and methods declared in the class extension.
*/
#implementation MyClass
/*Therefore we can use synthesize ;-)*/
#synthesize aPrivateProperty;
- (void)aPrivateMethod {
//Some code there
}
#end
But this is (from what I've seen) rarely used:
#interface MyClass : NSObject {
iVar *aProtectedIVar;
#public
iVar *aPublicIVar;
iVar *aSecondPublicIVar;
#protected
iVar *aSecondProtectedIVar;
#private
iVar *aPrivateIVAr;
}
#end
Why modifiers like #private, #protected and #public are not used so much in Objective-C if they are available?
Access modifiers for instance variables are rarely used because they expose more information about the structure of your object than you may wish to allow others to see. An exposure of a public variable is binding on all future implementations to have the same variable. Property, on the other hand, hides the variable, letting you change your mind later on, and compute result instead of storing it.
Property access is highly optimized in Objective-C, so there is virtually no run-time hit for exposing a property instead of a variable. Since you gain flexibility for free by switching to property, exposing variables with #public is rarely used.
I was interested why class extension, (like from example above) is used more often than #private modifier
Because class extension lets you place private properties with your .m file, rather than your .h header file. Headers included from other .m files create compile-time dependencies, which are easily avoided by placing implementation details into class extensions.
You can declare a global variable in three places.
If you declare this in .h is public:
#property (nonatomic, strong) NSString *publicString;
Instead if you declare the same in .m is private there are no need for the second way.

Can the ivar variable created automatically by properties accessible by the child class? [duplicate]

Since recent runtimes in iOS, we are able to define properties that will generate accessors for instance variables. From what I understand, it is not mandatory to declare the instance variable used since it will be automatically done for us.
For example, if I write:
#interface MyFirstClass
#property (readonly, nonatomic) int size;
#end
and in the .m
#implementation MyFirstClass
#synthesize size;
#end
Then an instance variable named "size" will be added for me and a method called "-(int)size" will be implemented.
The problem is that when I create a second class MySecondClass which is a subclass of MyFirstClass, it seems that I can't access the instance variable size within this subclass:
#interface MySecondClass : MyFirstClass
#end
#implementation MySecondClass
- (id)init {
if (self = [super init]) {
size = 10; // this yields and error
}
return self;
}
#end
Are the automatically created instance variables private? Is there a possibility to set them as protected so I can access them in subclasses?
I know there is the possibility to declare the instance variable myself, but I'm just wondering...
With a superclass like this it works: (Is it because it's expressly declared as protected?)
#interface MyFirstClass {
int size; // defined expressly and used as #protected
}
#property (readonly, nonatomic) int size;
#end
Thank you for your help!!
Nicolas.
Any instance variable not declared in the main interface is automatically private, and this cannot be overridden. If you try to use a scope modifier when defining instance variables in the implementation, you will get an error that the specification is inconsistent.
The reason for this is that there is usually only one class per implementation file, which means the compiler doesn't know about the instance variable when compiling other classes. If you have multiple classes in the same file, the compiler could know about it, but you still aren't allowed to override the scope. Possible reasons in this case could be for consistency, or just so the compiler doesn't have to look in so many places for instance variables.
Use:
self.size = 10;
That will map to setSize method.

Objective-c Differences

What the difference between declaring an #property in .h or .m file
#property (nonatomic, readwrite, assign) BOOL notificationDidLaunch;
Is it to do with the scope of the variable?
Also in the .h file whats the difference between declaring a string with the brakets like so
#interface AppDelegate : NSObject < UIApplicationDelegate > {
NSString *hat;
}
and doing it outside of them like below
#property (nonatomic, strong) NSString *hat;
As Tiago says, putting an #property declaration inside a class extension in the .m (implementation) file, is a way to make the property private so only the class itself can access it. When declared in the .h (public interface file), it is visible to all code that imports that .h file. Keep in mind that #properties are really just a convenience for declaring and synthesizing accessor methods, and as with all methods in Objective-C, they're never truly private. The best you get is a compiler warning that no public interface declares the method in question if you try to use a non-public method in another class.
For the second part of your question, this declares an instance variable ("ivar") called myString:
#interface MyClass : NSObject
{
NSString *myString;
}
While this declares a property called myString:
#property NSString *myString;
The difference between an instance variable and an #property is more significant than just saying that an ivar is accessible only by your class's instances. Declaring an ivar adds a variable to a class's structure in memory. In contrast, #properties declare/define methods on a class. By default, these methods set/get the value of an associated, and similarly named ivar, but that's not a requirement, and it is perfectly acceptable and quite common to have methods for an #property that don't access an ivar directly. Say for example a class that has a firstName and lastName properties backed by _firstName and _lastName ivars, along with a third, fullName property that simply concatenates the value returned by the firstName and lastName getter methods together (and/or splits a two part name in its set method).
A summarized explanation
A #property inside the .m is private to the class and in the .h is public.
The difference between declaring inside brackets or without brackets is the meaning of the variable.
Inside the brackets you declare an instance variable (or ivar) that is meant to be acessible only by your classes' instances. A property (declared in the .h) is meant to be acessible by any class.
Properties
A #property essentially defines a set and a get that you can override. When you do:
AppDelegate myAppDelegate;
myAppDelegate.hat = #"A hat":
You are essencially doing:
[myAppDelegate setHat:#"A hat"]
And when you do
myAppDelegate.hat //so you can get the property's value
you are essencially doing
[myAppDelegate hat]
Overriding Sets and Gets
When you do #synthesize hat = _hat you are essentially creating a get and a set that has an instance variable _hat associated. This instance variable should only be accessed in your gets/sets and even inside your class you should use your sets/gets (using self.property)
You can override the set and get created by the #synthesize overriding the following methods:
- (void) setHat:(NSString*) aHat
- (NSString *) hat

Quick inquiry about ivars scope [duplicate]

If you have a property in your public interface like the following
#interface MyClass : NSObject
#property(strong) NSString *myProp;
#end
And then synthesize it, in effect synthesizing the variable:
#implementation MyClass
#synthesize myProp = _myProp; // or just leave it at the default name..
#end
What is the visibility of the instance variable _myProp? That is, is this considered #public, #protected or #private? I'm guessing since MySubClass could inherit from MyClass then it would also get the properties (naturally), but would it also inherit the instance variable visibility?
What difference does it make if I put the property in a class extension? That would hide the property from subclasses, and I'm guessing the instance variable, too. Is this documented anywhere?
A synthesized ivar is completely invisible to all code that cannot see the #synthesize line (which basically means anything outside of the .m file). It's not #protected, it's not #private, it's simply unknown. With a #private ivar, other code trying to access it will be told that it's private, but with a synthesized ivar, other code trying to access it will be told that the field simply doesn't exist.
As a thought experiment, try imagining a situation where the ivar acted like it was #protected. You make a subclass, and you muck about with the ivar there. Now you go back to the superclass and change #synthesize myProp to #synthesize myProp=foo. What happens in the subclass? When the compiler processes the subclass, it cannot see the #synthesize line, so it would have no idea that you just changed the name of the ivar. In fact, it cannot even tell if the property is backed by an ivar at all, or if it's implemented with custom-written accessor methods. I hope it's obvious why this means that the subclass cannot possibly access the ivar, and neither can any other class.
That said, I'm not quite sure what the compiler does if you write code in the same .m file that tries to access the ivar. I expect it will treat the ivar as #private (since the compiler can, in fact, see that the ivar exists).
Also, none of this has any bearing on the runtime methods. Other classes can still use the obj-c runtime methods to dynamically look up your class's ivar list and muck about with it.
If it is declared in your interface it is virtually public when using the #property declarative. If you want to use #property declaratives and keep them property truly private, you should create a private category in your implementation.
MyClass.h
#interface MyClass : NSObject {
#private
NSObject* foo;
}
#end
MyClass.m
#import "ClassWithPrivateProperty.h"
#interface MyClass ()
#property (nonatomic,retain) NSObject* foo;
#end
#implementation MyClass
#synthesize foo;
// class implementation...
#end
A synthesized variable acts as if declared #private:
#interface Garble : NSObject
#property (copy) NSString * s;
#end
#implementation Garble
#synthesize s;
#end
#interface Bargle : Garble
#end
#implementation Bargle
- (void) useS {
NSLog(#"%#", s); // error: instance variable 's' is private
}
#end
I swear I've seen this in the docs, but I can't find it right now. Will update if I track it down.
You can create a dynamic property and indicate it to the compiler that its instantiation would be at run time.
And then in your subclass write your own getter or synthesize the property.
#interface BaseClass : NSObject
#property (nonatomic, strong) NSString *ThisWillBeSynthesizedInRespectiveSubclasses;
#end
#implementation BaseClass
#dynamic ThisWillBeSynthesizedInRespectiveSubclasses;
#end
In Sub classes
#interface Subclass : BaseClass
#end
#implementation Subclass
#synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;
#end
or you write your own setter / getter methods.
Hope this helps !
Other classes have access to everything that they #include. In other words, to everything that is inside your header.
If something appears only in your implementation file, other classes (including subclasses) don't know it exists. A synthesized property is like that. Other classes know only about the property (a property means a getter and a setter method) but they don't know anything about the inner implementation of its methods.
Note, that the access specifiers (public/private/protected) in obj-c are only a hint to the compiler that even if something appears in the header file, it can't be accessed. The runtime does not check it in any way.
What happens if you put it into a class extension? Note that a property is a set of two methods. You just hide the methods from every class which includes your class main header but not the class extension header.
We use this for example to declare a property as readonly and in class continuation we declare it as readwrite. Then, we can use the setter only from inside of the class.

What is the visibility of #synthesized instance variables?

If you have a property in your public interface like the following
#interface MyClass : NSObject
#property(strong) NSString *myProp;
#end
And then synthesize it, in effect synthesizing the variable:
#implementation MyClass
#synthesize myProp = _myProp; // or just leave it at the default name..
#end
What is the visibility of the instance variable _myProp? That is, is this considered #public, #protected or #private? I'm guessing since MySubClass could inherit from MyClass then it would also get the properties (naturally), but would it also inherit the instance variable visibility?
What difference does it make if I put the property in a class extension? That would hide the property from subclasses, and I'm guessing the instance variable, too. Is this documented anywhere?
A synthesized ivar is completely invisible to all code that cannot see the #synthesize line (which basically means anything outside of the .m file). It's not #protected, it's not #private, it's simply unknown. With a #private ivar, other code trying to access it will be told that it's private, but with a synthesized ivar, other code trying to access it will be told that the field simply doesn't exist.
As a thought experiment, try imagining a situation where the ivar acted like it was #protected. You make a subclass, and you muck about with the ivar there. Now you go back to the superclass and change #synthesize myProp to #synthesize myProp=foo. What happens in the subclass? When the compiler processes the subclass, it cannot see the #synthesize line, so it would have no idea that you just changed the name of the ivar. In fact, it cannot even tell if the property is backed by an ivar at all, or if it's implemented with custom-written accessor methods. I hope it's obvious why this means that the subclass cannot possibly access the ivar, and neither can any other class.
That said, I'm not quite sure what the compiler does if you write code in the same .m file that tries to access the ivar. I expect it will treat the ivar as #private (since the compiler can, in fact, see that the ivar exists).
Also, none of this has any bearing on the runtime methods. Other classes can still use the obj-c runtime methods to dynamically look up your class's ivar list and muck about with it.
If it is declared in your interface it is virtually public when using the #property declarative. If you want to use #property declaratives and keep them property truly private, you should create a private category in your implementation.
MyClass.h
#interface MyClass : NSObject {
#private
NSObject* foo;
}
#end
MyClass.m
#import "ClassWithPrivateProperty.h"
#interface MyClass ()
#property (nonatomic,retain) NSObject* foo;
#end
#implementation MyClass
#synthesize foo;
// class implementation...
#end
A synthesized variable acts as if declared #private:
#interface Garble : NSObject
#property (copy) NSString * s;
#end
#implementation Garble
#synthesize s;
#end
#interface Bargle : Garble
#end
#implementation Bargle
- (void) useS {
NSLog(#"%#", s); // error: instance variable 's' is private
}
#end
I swear I've seen this in the docs, but I can't find it right now. Will update if I track it down.
You can create a dynamic property and indicate it to the compiler that its instantiation would be at run time.
And then in your subclass write your own getter or synthesize the property.
#interface BaseClass : NSObject
#property (nonatomic, strong) NSString *ThisWillBeSynthesizedInRespectiveSubclasses;
#end
#implementation BaseClass
#dynamic ThisWillBeSynthesizedInRespectiveSubclasses;
#end
In Sub classes
#interface Subclass : BaseClass
#end
#implementation Subclass
#synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;
#end
or you write your own setter / getter methods.
Hope this helps !
Other classes have access to everything that they #include. In other words, to everything that is inside your header.
If something appears only in your implementation file, other classes (including subclasses) don't know it exists. A synthesized property is like that. Other classes know only about the property (a property means a getter and a setter method) but they don't know anything about the inner implementation of its methods.
Note, that the access specifiers (public/private/protected) in obj-c are only a hint to the compiler that even if something appears in the header file, it can't be accessed. The runtime does not check it in any way.
What happens if you put it into a class extension? Note that a property is a set of two methods. You just hide the methods from every class which includes your class main header but not the class extension header.
We use this for example to declare a property as readonly and in class continuation we declare it as readwrite. Then, we can use the setter only from inside of the class.