If I understand this correctly, copy enforces the setter to create a copy of the object passed in. However, if I use it together with readonly, there won't be a setter. So is my assumption correct, that combining #property (copy, readonly) doesn't make any sense or am I missing something?
It does make sense. For instance, if you want to access a property's setter in your implementation only:
#interface MyClass : NSObject
#property (nonatomic, copy, readonly) NSData *data;
- (id)initWithData:(NSData *)data;
#end
and in the class continuation in the .m file:
#interface MyClass ()
#property (nonatomic, copy, readwrite) NSData *data;
#end
Note that the copy, readonly declaration in the public header is required in this case!
According to Apple's documentation (which I've linked here for you):
copy
Specifies that a copy of the object should be used for assignment.
The previous value is sent a release message.
The copy is made by invoking the copy method. This attribute is valid
only for object types, which must implement the NSCopying protocol.
So yes, you're correct... readonly creates a getter method and copy would be effectively ignored, since there's no setter method that does assignment.
You are correct, it does not make sense to have both.
I think, if I saw such a property, on read, I would expect to receive a distinct returned object to the ivar unless the returned object was advertised to be immutable.
If I have
#property (readonly, copy) NSMutableArray* foo;
and I do this:
NSMutableArray* myFoo = [theObject foo];
[myFoo addObject: #"string"];
NSMutableArray* myOtherFoo = [theObject foo];
I would expect myOtherFoo not to have the extra string in it that myFoo has.
Note: I haven't verified this yet.
I have checked it now and my expectation is incorrect. I think I would regard that as a bug.
Related
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;
}
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'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.
I want to use ARC in my simple class where I store some values to pass into another class. And I want to know what reference I have to use in the property. To use it in ARC, I have this:
#interface MyItem : NSObject
#property (retain) NSString *valueID;
#property (retain) NSString *itName;
#property (retain) NSDate *creationDate;
#property (assign) float rating;
This is a very simple class, and I want to know how to use it in ARC. What reference do I have to use? Do I have to use a copy for the NSString etc?
EDIT:
If I have a UIViewController, and I want to use a property for NSString and for MyItem object like this:
#interface MyViewController : UIViewController
#property (nonatomic, retain) NSString *myString;
#property (nonatomic, retain) MyItem *newItem;
What reference do I have to use for NSString and for MyItem object?
You want to use strong instead of retain. And yes, you should still use copy for NSStrings. The use of copy has nothing to do with ARC; you want copy because if someone assigns an NSMutableString to your property you don't want the string changing behind your back. Using copy gives you an immutable snapshot of the mutable string at the point where the assignment took place.
This is the recommended way to declare the properties in your view controller example:
#interface MyViewController : UIViewController
#property (nonatomic, copy) NSString *myString;
#property (nonatomic, strong) MyItem *newItem;
The NSString could be declared as strong as well, but copy is almost always preferable for strings (and really any immutable type that has a mutable variant, e.g. arrays, dictionaries, etc).
(nonatomic, strong) is what i use but here is the documentation
or for quick reference
Setter Semantics
These attributes specify the semantics of a set accessor. They are
mutually exclusive.
strong Specifies that there is a strong (owning) relationship to the
destination object.
weak Specifies that there is a weak (non-owning) relationship to the
destination object.
If the destination object is deallocated, the property value is
automatically set to nil.
(Weak properties are not supported on OS X v10.6 and iOS 4; use assign
instead.)
copy Specifies that a copy of the object should be used for
assignment.
The previous value is sent a release message.
The copy is made by invoking the copy method. This attribute is valid
only for object types, which must implement the NSCopying protocol.
assign Specifies that the setter uses simple assignment. This
attribute is the default.
You use this attribute for scalar types such as NSInteger and CGRect.
retain Specifies that retain should be invoked on the object upon
assignment.
Atomicity
You can use this attribute to specify that accessor methods are not
atomic. (There is no keyword to denote atomic.)
nonatomic Specifies that accessors are nonatomic. By default,
accessors are atomic.