is there a better way to write the property in OC? - ios

i have property like this:#property (nonatomic, assign, readonly) CGRect frame;in the example.h file,i think this statement is to tell other class that the frame property is readonly and it also tell the compiler do not need to synthesize a setter method.
is that right to say that the class itself can use the instance variable _frame(the self.frame still can not use) in the .m file? if so,is there a better way to use this instance variable _frame? redeclare this property to readwrite in the class extension or redeclare the instance variable in class extension like this(i have found many guys write like this,but i do not understand what is the benefit of doing so?):
#interface example () {
CGRect _frame;
}
#end
#implementation example
or i just need do nothing?

My understanding about property as follows:
1.program find name of property in class of receiver when you take dot operator(.).
Like this: tt.frame (example* tt = [[example alloc] init];)
2.Then program find relationship between name of property(binding with synthesized method same name as name of property) and instance variable.
The way for that is: #synthesize frame=_frame;
(frame is name of property,_frame is instance variable. Binding name of property and instance variable.If you don't do like this,compiler will provide a instance variable (frame,then modify this frame, not _frame you designed.)when you choice 64-bit environment.Or compiler will give you a warning, if you choice 32-bit environment)
3.Call method for the real instance variable.

Related

Is it allowed to duplicate variable name in same class?

I have a block of source code getting from Github. It looks like:
Header file
#interface VTDUpcomingDisplayData : NSObject
#property (nonatomic, readonly, copy,) NSArray* sections; // array of VTDUpcomingDisplaySection
+ (instancetype)upcomingDisplayDataWithSections:(NSArray *)sections;
#end
Implementation file
#import "VTDUpcomingDisplayData.h"
#interface VTDUpcomingDisplayData()
#property (nonatomic, copy) NSArray* sections;
#end
#implementation VTDUpcomingDisplayData
+ (instancetype)upcomingDisplayDataWithSections:(NSArray *)sections
{
VTDUpcomingDisplayData* data = [[VTDUpcomingDisplayData alloc] init];
data.sections = sections;
return data;
}
This block code has two variable name called 'sections' but builds successfully. I have two questions:
First of all, I do not understand why this is allowed to happen?
Second, how to call exact the variable I want in source code?
It's normal in Objective-C, called override property attribute or redeclaring a property. You can declare a property is readonly in interface, and make it's readwrite (There’s no need to specify the readwrite attribute explicitly, but in this case You better write it) in implement.
Here's Apple document about redeclaring a property in class extension
Class extensions are often used to extend the public interface with
additional private methods or properties for use within the
implementation of the class itself. It’s common, for example, to
define a property as readonly in the interface, but as readwrite in a
class extension declared above the implementation, in order that the
internal methods of the class can change the property value directly.
First of all, I do not understand why this is allowed to happen?
Just because it's normal behavior in Objective-C
Second, how to call exact the variable I want in source code?
It's just once property, You can access it as readwrite in internal method. But in other class it's still readonly
Both declarations refer to the same property (and underlying instance variable).
However, the properties are declared differently in the header and the implementation. In the header, which defines the interface to be used by callers of this object, the property is declared readonly. In the implementation of the class the same property is missing the readonly attribute, i.e. it is read/write.
This is to allow the implementation of the class read and write access to the property but limit users of the class to only read from the property. Everybody is accessing the same property (instance variable), the only difference is the access rights of the different callers.

instance variables only visible internally in class

NOTE: I am only talking about .m file here.
I am confused by these two things, both are said to be the way to declare internal instance variable:
Way 1:
#interface MyClass ()
// Declare instance variable which is only visible in this class
#end
#implementation MyClass
...
#end
Way 2:
#implementation MyClass {
// Declare instance variable which is only visible in this class
}
...
#end
What are the differences between these two ways of declaring instance variables?
In terms of functionality, there is no difference.
Declaring the ivars in a class extension -- the #interface MyClass() {...ivars...}#end pattern -- does allow you to move the ivar declaration to a header file that could then be used by other classes for direct access for internal-only use, for example.
After the "#interface" line, you can add instance variables within curly braces. That's instance variables, not properties. After the curly braces, or immediately after the "#interface" line if you have no curly braces, you add methods and properties.
So your first comment is wrong. Instance variables can only be added within the curly braces. Properties generate instance variables (usually but not always), but they are not instance variables.
Besides ivar, properties also generate setter and getter method if necessary (according your property attribute). But if you implement the setter and getter synchronously, compiler would not synthesize ivar, since the compiler will assume that you are taking control over the property implementation and won’t synthesize an instance variable automatically.
In Objective C the { } it’s the area where you declare instance variables. You can also use access member declaration in that section like #private #public & #protected. When you declares the "ivars" outside the {} the variable will be a file-scope variable (kind of static) and it won't be an instance variable of your class.
If you use properties (#property) the compiler is smart enough and will create its own ivars with its corresponding setter and getter.
Using a class extension in the implementation file allows you to add ivars or properties (and methods) that are only accessible by the implementation of the class extension. It also allows you to overwrite access of base classes like properties or private methods.

Objective-C member variable vs property in source file

I understand the difference between member variable and property in Object-C, but there is one thing make me confused. See the following code.
test.h
#interface test : NSObject
#end
test.m
#interface test()
{
NSString *memberStr;
}
#property (nonatomic, strong) NSString *properyStr;
#end
As showed, the memberStr and propertyStr can't be see by outside. I want to know what is the difference between them. Because I don't how to chose the solution when i want to use local variable.
Thanks!
properyStr will have the getters and setters generated automatically.
you can define custom setter for propertyStr as below. When you use self.propertyStr, it will create a default object for you. It will be useful for initialising objects like NSMutableArray, NSMutableDictionary etc.
- (NSString *)properyStr
{
if(_propertyStr == nil)
{
_propertyStr = #"";
}
return _propertyStr;
}
memberStr will not have these options.
I understand the difference between member variable and property in Object-C
I'm not sure that you do.
A member variable is a variable that's visible only within the scope of instance methods.
A property is some attribute of the class that can be set or get. The compiler will write appropriate getters and, optionally, setters, and will organise storage for itself, unless you override any of those things.
Both member variables and properties can be declared either in the #implementation or in the #interface.
A member variable can never be accessed directly by unrelated classes, regardless of where it was declared. If it's in the #interface then it can be accessed by subclasses.
A property can always be read and, optionally, written by any other class, regardless of where it was declared. External classes can use the key-value coding mechanism even if the #property isn't visible to them.
Questions you may therefore be likely to ask:
Q) Why would I put a member variable into the #interface?
A) It's unlikely you would. It will expose it to subclasses but usually wanting to do so is a design flaw. However, in olden times you had to put all member variables into the #interface for reasons of how the old Objective-C runtime worked. So older code and stuck-in-their-ways programmers will still sometimes follow this pattern.
Q) Why would I declare a property visible only to the #implementation?
A) It's unlikely you would. However in olden times this was the only way to create member variables that weren't visible in the #interface so was the way people did most member variables for a brief period. Similarly, you could declare something, say retain, then use the getter/setter and assume correct memory management was going on, so it acted as some syntactic sugar in the days before ARC was introduced. As with the previous answer, there are therefore some people who still do so through habit and some code that still does so on account of being older. It's not something you'd often do nowadays.
EDIT: a better summary: properties adjust your class interface. Member variables adjust its implementation. In object-oriented programming you should be thinking of the two things as entirely disjoint.
One of the main purposes of object-oriented programming is to have a bunch of discrete actors that say "I can do X" with exactly how they do it being nobody else's business.
A property says what a class can do. A member variable is for the benefit of how the class does it.
Semantically they're completely separate issues.
First of memberStr is an instance variable or ivar.
There is no need to have memberStr any more if you have a property setup for this all you need is.
#interface test()
#property (nonatomic, strong) NSString *properyStr;
#end
The reason for this is that the ivar will be automatically created for you along side the setter and getter methods.
The only difference between declaring the property in the implementation files (.m) interface over the interface file (.h) is that it will be private to this class only. There are many advantages for having this such as maybe you don't want anything outside of the class to know about it but you want the property to be in scope for this class still. One thing that they are used for in this manner is when you have a readonly property declared public but you still want the setter to be in scope for this class. So you may have something like
.h
#interface MyObject : NSObject
// Other classes can see this property as it is public however they can only see
// it's getter and not the setter
#property (nonatomic, readonly) NSString *firstName;
#end
.m
#interface MyObject()
// But we still want to use the setter for this class only.
#property (nonatomic, strong) NSString *firstName;
#end
Otherwise except for being private to that class only; having the property in the implementation file (.m) will be the exact same as having it in the interface file (.h) they will act and do the same thing.

IOS: property and self [duplicate]

This question already has answers here:
iOS: Usage of self and underscore(_) with variable [duplicate]
(3 answers)
Closed 8 years ago.
When I declare an NSString I simply do:
NSString * my_string; (in interface of my .h)
If I want to allow access to this string from other classes I add a property in this way
property (nonatomic, strong) NSString *my_string;
and I write the synthesize
synthesize my_string; (in .m)
Now I have some question about:
If I use a property, must I also use the simple declaration in interface?
If I use my_string as a property, must I always use self. before?
If I use a property, is it necessary to write #synthesize for each? (because I saw that sometimes it's not necessary.
If I use a property, must I also use the simple declaration in interface?
No, generally you just want to use the #property (it will quietly add an instance variable for you).
If I use my_string as a property, must I always use self. before?
You don't need to but you should. Using self. calls the accessor method to get the variable contents. Not using self. accesses the instance variable directly. So, if you add a custom accessor in the future you will need to refactor.
Often you will reuse the same variable multiple times. In this case, call self., but use it to set a local variable that you then use throughout the method (in this way the accessor is only called once).
If I use a property, is it necessary to write #synthesize for each? (because I saw that sometimes it's not necessary.
No, the compiler will add:
#synthesize propertyName = _propertyName;
for you, and that is a good approach to follow (separating the property name from the instance variable name).
NO
NO, using self. will execute accessor method, you can use it with name _my_string and then you'll access the variable directly. If you want a different variable name for your property then you must use synthetize with that name
NO, xcode will synthetize it automatically with the variable named _my_string
It's becoming more and more appropriate to use properties in all cases anymore. You can declare "private" properties inside a header extension inside the .m file if you don't want to expose them to outside classes. Say you have a property called name in the .h file:
#property (nonatomic, strong) NSString *name;
Users of this class can access the name property by saying theVariable.name, inside your .m file you need to access this property with self.name. However you can access the ivar like so:
_name = #"John Smith"
This will skip the property and go directly to the ivar. In this case if you had an overriden setter it won't be called.
You no longer need to synthesize properties. Xcode will automatically provide this:
#synthesize name = _name;

_iVar and #property?

I see someone writes codes like this
#interface SomeClass:<NSObject>{
NSString * _iVar;
}
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
But I always like write codes like this:
#interface SomeClass:<NSObject>
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
They all works fine, and I can use an instance someClass to get iVar "someClass.ivar".I just know why?
You now don't even have to synthesize the iVars anymore. The latest Xcode will automatically create a backing instance variable for each property, with the property name prefixed with an underscore.
In Objective-C when you are using anything via "." (dot syntax), it is accessing property. You have declared and synthesize a property with name iVar, so you can access it with someClass.iVar.
When you are declaring a property, a variable is automatically created with it. So, even if you do not create a variable, it will be there.
To avoid ambiguity, people are creating properties and iVar with different names. So, they can identify if the variable is being used or a property is being used. In that case people let the compiler know that a particular variable is associated with a property by low way:
#synthesize iVar = _iVar;
If you want access variable directly outside the class instead of property, you should use "->" (arrow syntax).

Resources