It seems that it's unnecessary to use #property when customizing both getter and setter method. Like this.
#property (nonatomic) Person *spouse;
#property (nonatomic, copy) NSString *lastName;
#property (nonatomic, copy) NSString *lastNameOfSpouse;
If I use customize getter and setter like this
- (void)setlastNameOfSpouse:(NSString *)name {
self.spouse.lastName = name;
}
- (NSString *)lastNameOfSpouse {
return self.spouse.lastName;
}
It seems that #property won't synthesis any getter or setter method.
I'd like to know that in this example whether I still need to use #property and whether the attribute used in #property takes effect.
You should definitely still use a property in this case.
So considering this line:
#property (nonatomic, copy) NSString *lastNameOfSpouse;
This is a declaration of the API. If you did not include it in your interface, then other classes could not easily access this property. It is also promise that somehow, objects of this class will respond to -lastNameOfSpouse and -setLastNameOfSpouse:. There are a lot of different ways that promise could be fulfilled. One common way is to use compiler-generated methods. Another way is to implement the methods yourself. Another way is to add method implementations at runtime. Another way is to use the message dispatching system. There are a lot of options. Which option you use isn't relevant to the interface.
Before we had properties, we had to declare both methods by hand in the interface:
#interface Person
- (NSString *)lastNameOfSpouse;
- (void)setlastNameOfSpouse:(NSString *)name;
#end
You then had to write each implementation by hand. This was somewhat tedious (so tedious that an entire tool existed purely to write these for you). ObjC2 simplified this pattern by calling it a "property" and allowing it to be declared in a single line (along with some hints about how the methods were expected to be implemented). On request (#synthesize), the compiler would create the most common implementation for you. Later compiler innovations auto-created implementations for any properties you failed to implement yourself. That made things even nicer. But it's all just compiler niceties that wrap up an API promise. And that's why you include it in the interface.
You can use your own getter/setter with effect of generated one:
#synthesize lastNameOfSpouse = _lastNameOfSpouse;
- (void)setLastNameOfSpouse:(NSString *)lastNameOfSpouse
{
_lastNameOfSpouse = lastNameOfSpouse;
// Add-on code like self.spouse.lastName = name;
}
- (NSString *)lastNameOfSpouse {
return _lastNameOfSpouse;
}
Related
I'm starting my adventure with Objective-C and iOS and I've got one thing that I don't know how to use correctly and this is literally blowing my mind.
Many tutorials have private class variables in .m files defined like this:
#interface ViewController (){
#property (nonatomic, strong) NSMutableArray *myArray;
}
or like this:
#implementation ViewController
NSMutableArray *myArray;
#end
In the first example I can use _myArray instead of self.myArray, which I like, but should I put all my private variables in interface files? What's the difference between those two variables? When should I use one instead of another, and which is safer?
The difference is that:
_myArray is instance variable.
self.myArray is calling a getter method on your object.
Using self.myArray = nil makes the variable go through its setter and therefore release the object when ARC is not used).
If the property is declared with atomic (default value) which means access the variable is thread-safe with the cost of performance
nonatomic property means race condition can happen when access the variable or property from multiple threads.
In general, use atomic for object shared with multiple threads and nonatomic for UI or not shared object.
Attention, you will get compiler error with your code:
#interface ViewController (){
#property (nonatomic, strong) NSMutableArray *myArray;
}
-> you must move #property... outside of {} of your header.
#interface ViewController (){
//
}
#property (nonatomic, strong) NSMutableArray *myArray;
A couple of thoughts:
The first example is not syntactically correct. You probably meant the following, which defines a declared property inside the class extension:
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *myArray;
#end
A property will:
Synthesize an instance variable called _myArray (or if you specify a #synthesize directive, you can control the name of this instance variable);
Synthesize accessor methods, notable a myArray getter that retrieves the value and a setMyArray setter that sets the value;
Provide other features such as key-value coding, etc.
On the other hand, the following declares a global variable:
#implementation ViewController
NSMutableArray *myArray;
#end
Globals are a very different beast, shared amongst all of the various instances of this class (and across the whole app). In this case (some mutable array used by a class instance), a global is likely not what you intended.
If you intended to define an instance variable, you could do:
#implementation ViewController
{
NSMutableArray *myArray;
}
#end
Or, perhaps better than defining this ivar in the #implementation like that, one would generally define them within the class extension's #interface:
#interface ViewController ()
{
NSMutableArray *myArray;
}
#end
I suspect you didn't actually intend to compare the global variable to a instance variable (ivar) or property, but rather were asking the rationale for privately using a property vs. ivar within a class implementation:
Bottom line, within a particular class, using ivars is a perfectly acceptable practice, but many of us use private properties defined in class extensions. The overhead is minimal and it abstracts the code away from the implementation details of the ivar. For example, you can customize one or more of the accessor methods at some future date and have minimal impact on the rest of the class implementation. But it's a matter of personal preference.
#property creates your setters and getters the other one does not.
yes, #property is automatically creates setter and getter.
additionally, you can setting property's attribute.
(read-only/readwrite, nonatomic/atomic, strong/weak.. etc)
accessing instance variable by getter & setter(instead of using pointer to direct access) make data encapsulated.
it is common and important concepts of Object-Oriented Programming.
read this for understanding.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
sorry for poor english. :<
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.
I've been reading the tutorials and I'm right now designing the model's architecture, and since I'm new to Objective-C, I'm not sure if the standards are like Java where you have public setter/getter and private attribute. This is 1 question I'd like to ask.
If the standards are so, declaring private properties are done in the *.m file #interface, but how do I #syntetize a setter/getter and how do I call them from outside: is it like [object SetProperty:property] ?
If the standards are different, can I get an example of a model class?
Thanks in advance.
A property is essentially a promise that a class provides certain accessor methods. For example:
#property(strong, nonatomic) Foo *foo;
is a promise that the class provides -foo and -setFoo: methods. So, if you want the accessors to be public, declare the property in your class's public interface (i.e. in the header file) and be done with it.
It's true that the instance variable that backs that property (_foo, unless you specify a different name) will then be accessible, but it's very poor form to access another object's instance variables directly. Many things in Objective-C are governed by convention and that's generally enough to avoid problems. Also, a given property doesn't have to be backed by any instance variable at all: a property like fullName might be computed from other properties like firstName and lastName, so there's good reason beyond mere convention for clients to avoid accessing ivars directly.
The common approach if you want to give access to your attribute is to use the keyword #property in the .h file of your class to define a property. This will automatically define a setter and a getter and you don't need to synthesise your property as of Xcode 4.4.
Your private attribute will be accessible within your .m file and will have the name of your property with "_" as a prefix by default.
You can create a private property and create public setter/getter method of your own. From this method you can assign or retrieve the value back.
#interface Person : NSObject
-(void)setTheName:(NSString *)fullName;
-(NSString *)theName;
#end
Implementation file:
#import "Person.h"
#interface Person()
#property(atomic) NSString *fullName;
#end
#implementation Person
-(void)setTheName:(NSString *)fullName{
self.fullName = fullName;
}
-(NSString *)theName{
return self.fullName;
}
#end
In the above is private however you can check the selector still exists(but throws a warning)
if ([p respondsToSelector:#selector(setFullName:)]) {
[p performSelector:#selector(setFullName:) withObject:#"Anoop"];
}
NSLog(#">>>> %#",[p theName]);
Output will be :
>>>> Anoop
However it is seldom required to set any private property from outside. If that is the requirement we can make the property public.
Well it is true that Objective-C uses another terminology than most of the other languages like Java. If I get what you're asking, if you want a property to be directly available outside the class, the property must be declared in the .h file. However if you want to hide the implementation of your code, you can declare a property in the .m file and provide setters/getters to the outside world just returning the information you want to be visible.
The #synthesize clause is to me a simpifier. By synthesizing a property the getter/setter will be automatically implemented and you don't need to do it yourself.
Does this answer your question ?
Understand that declaring a property causes the compiler to create accessor for you . so if i require a pseudo private property personally I declare it in the implementation, if i need pseudo public property i declare it in the header. public getter / private setter can be handled as indicated below. There is no need to create your own setters and getters prefer using an attribute as it saves writing setters/getters ;
in the header (.h)
#interface Person : NSObject
#property (nonatomic, readonly) NSString *fullName;
#end
in the implementation file (.m)
#import "Person.h"
#interface Person()
#property (nonatomic, readwrite) NSString *fullName;
#end
#implementation Person
... whatever this class does
// self.fullName = #"John Doe";
#end
I'm beginning to learn how use Core Data for my app, and I have a question about setter and getter with NSManagedObject.
In my old models I was using this syntax to declare attributes :
#interface MyModel : NSObject
{
MyAttributeOfClass *_myAttributeOfClass
}
- (void)setMyAttributeOfClass:(MyAttributeOfClass *)anAttributeOfClass;
- (MyAttributeOfClass *)myAttributeOfClass;
I know, I could use #synthesize for doing this stuff. But if I use #synthesize with a public attribute like :
#property (nonatomic, strong) MyAttributeOfClass *myAttributeOfClass;
A developer could bypass my setter and directly set a value for myAttributeOfClass by doing this: myAttributeOfClass = bar;. I don't want to allow this behaviour because I use a setter to perform an action. If this action is not done, my class will no longer work correctly.
So, now I am migrating my old model to Core Data model subclassed from NSManagedObject.
But when I generate classes from my data model, the attributes are declared this way:
#property (nonatomic, retain) MyAttribute *myAttribute;
So, a developer can set a value for this attribute without calling a setter: myAttribute = bar; and I would like forbid it.
Any suggestions ?
Thanks !
The attributes of Core Data managed objects are not backed-up by instance variables. An attribute can be set using the property syntax:
object.myAttribute = bar;
or with Key-Value Coding:
[object setValue:bar forKey:#"myAttribute"];
and in both cases the setter method
-(void)setMyAttribute:(MyAttribute *)value;
is called. Setter and getter method are usually created dynamically at runtime, but you
can provide your own explicit setter and/or getter method.
However, it is possible to bypass the setter by calling the "primitive" accessor methods:
[object setPrimitiveValue:bar forKey:#"myAttribute"];
This is what a custom setter method would use, but anybody can call the primitive accessor,
there is no way to inhibit that.
My approach when I want to have a private setter is to have this in the header:
#property (nonatomic, strong, readonly) NSString* myProperty;
And then in the .m file add:
#interface MyClass ()
#property (nonatomic, strong) NSString* myProperty;
#end
Externally the property is read-only, but by defining a private category in the implementation file, the property is readwrite within the implementation.
Im just about to refactor my current iOS project to use ARC. And after previewing the changes to migrate my current code to ARC using the "Refactor to ARC" tool i xCode, i can see my current code conventions probably not suited for ARC. Because it adds alot of __weak / __strong etc to my ivars.
Heres how my current conventions are:
i define all instance variables as private or protected ivars. and all public variables i create a #property for.
#interface TestClass
{
#private
NSMutableArray* mArray;
NSString* mString;
BOOL mMyBoolean;
}
#property (retain, nonatomic) NSString* string; // public
#end
All objects i always back with a #property, to avoid dealing with release / retain so if i have a private variable that is a reference, i just create a category in the implementation. Struct (like mMyBoolean) i just leave define as a ivar.
#interface TestClass()
#property (retain, nonatomic) NSmutableArray* mArray;
#end
#implementation TestClass
#synthesize string = mString;
#synthesize mArray;
#end;
But because the new ARC is taking care of retain / release i properly dont need private variables to be backed by #property.
So what code conventions would be more appropriate? Ive been thinking about just defining properties in the interface like this:
#interface TestClass
{
#private
NSMutableArray* mArray;
BOOL myBoolean;
}
#property (strong, nonatomic) NSString* string;
#end
#implementation TestClass
#synthesize string;
#end
And dont use category properties for private properties. (also i removed the "m" prefix) and i dont define the backed ivar that #property should use, instead i just let xcode use its autogenerated?.
This is more of a style question, so...it's hard to answer objectively, but I will throw in my two cents. There is not anything wrong with what you are doing as far as I can see. If your goal is to see what you can do to have cleaner code, then I will share my naming conventions (though one man's junk is another man's treasure, so if you don't like it then...well tough haha, you don't have to take anything away from it).
1) iVars start with m and are never public.
2) Property synthesized to a variable name starting with underbar (_), no explicit backing variable unless I need inherited classes to be able to modify a read only variable internally, in which case I need to move it to the public interface (and I still name it with an underbar to indicate to myself that it is a property variable). Properties are meant to expose some info through an interface, but since the implementation has access to everything it doesn't make sense and I never use properties in private interfaces except for the following case:
3) Properties that lazy load, or otherwise have logic outside of simply assigning to a variable. In this case, if I only override the getter or setter (not both) I will still synthesize to (_) and override the desired method (no need for explicit variable). If I override both, I don't synthesize then obviously I need an explicit backing variable (don't forget to call the KVO methods ^^).
There is no "right" way to do this kind of stuff I imagine...the only guidelines that seems to be universal are
1) Do it in a way that you and your team can understand easily
2) Do it consistently
3) In the case of an API, do it in a way that is easily understandable from looking at only the header files.