What is the best practice?
Declare the property as nonatomic
Create custom getter too
Another possibility that I'm not aware of
and why prefer one of this solution rather another.
In most of the cases, you just need to provide implementation for setter and declare the property as nonatmoic. This will generate ivar with underscore prefix and you need to set the value in setter method.
You don't normally need to override getter unless you have special logic in getter or the property need to be atomic.
If you do want to provide getter (along with setter), you may need a backend ivar either by declare it in #implementation{ /*here*/ } or use #synthesize to generate one.
In case for atomic property:
#interface MyClass : NSObject
#property (atomic) id object; // atomic is default attribute
#end
#implementation MyClass
#synthesize object = _object; // to create ivar
- (id)object {
#synchronized(self) { // or use lock / atomic compare-and-swap
return _object;
}
}
- (void)setObject:(id)obj {
#synchronized(self) { // or use lock / atomic compare-and-swap
_object = obj;
}
}
#end
Related
I have 3 properties id_1, id_2, id_3
id_2 and id_3 are derived from id_1
id_1 can have public getter/setter
id_2 and id_3 only have readonly access.
So I need to override the setter for id_1 to set id_2 and id_3 for valid id_1
id_1 could come from NSUserDefaults which means in init, I need to set id_2 and id_3
So, I wanted to call setter of id_1 from init as if I was calling from outside of the class using ivar _id_1
That would give me a single implementation to set all the ids both during init phase or if called externally
My question is on following two lines that I have in my code as I am calling the setter for id_1 with argument as ivar _id_1
_id_1 = id_from_ns_user_defaults
[self setid_1:_id_1];
In few other SO articles I saw concerns around recursive loops
Custom Getter & Setter iOS 5
.h file
#interface UserCredentials : NSObject
#property (strong, nonatomic) NSString *id_1;
#property (readonly) NSString *id_2;
#property (readonly) NSString *id_3;
#end
.m file
#interface UserCredentials ()
#property (readwrite) NSString *id_2;
#property (readwrite) NSString *id_3;
#end
#implementation UserCredentials
- (id)init
{
self = [super init];
if (self) {
/* Is this valid in Objective-C */
_id_1 = id_from_ns_user_defaults
[self setid_1:_id_1];
}
return self;
}
- (void)setid_1:(NSString *)id
{
if (id && ![id isEqualToString:#""]) {
_id_1 = id;
_id_2 = convert2(_id_1);
_id_3 = convert3(_id_1);
}
}
#end
Your highlighted concern is around creating an assignment cycle. Because you are assigning to the ivar itself, you will not be creating a cycle. Remember that manipulating the ivar will not cause your getter/setter to be called -- it's just a pointer like any other pointer.
Setting an ivar to itself is not an issue unless you have done something in your setter implementation to make it an issue. In non-ARC systems, you could easily create a bad access error by implementing your setter with the wrong order:
- (void)setVal:(NSObject *)val {
[_val release];
_val = [val retain];
}
This is countered by using autorelease instead (or assigning to a temporary variable and releasing after the retain).
Most of the time, though, your setter won't be doing anything destructive when passed a new (or same) value. Your implementation does not do this.
Is there a way to define a setter method that will run on setting a property like:
i want to call
object.something = 0;
meanwhile in object class i want to achieve something like
- (void)setSomething:(NSInteger)something{
self.something = something;
// some other work too
}
What you want is called property.
you define property in class #interface like:
#interface MyClass()
#property (strong, nonatomic) SomeClass *object;
#end
It will automatically create ivar _object, setter and getter for it.
You can override accessor methods. But if you override both setter and getter, you need to synthesize property like:
#implementation MyClass
#synthesize object = _object;
//setter
- (void)setObject:(SomeClass *)object
{
_object = object;
}
//getter
- (SomeClass *)object
{
return _object;
}
//class implementation
#end
You can do it like this:
#property (nonatomic, weak, setter = setSomething:) UIImageView *photoImageView;
Anyway, setSomething: is the default method for a property named something. You just need to replace self.something with _something, as pointed in the comments.
Problem
I want to create an interface with this signature, but without auto-synthesized instance variables:
#interface MyObject : NSObject
#property (nonatomic, copy) NSArray *values;
#end
Question:
Is it possible to prevent instance variable to be auto synthesized in .m #implementaion, as I want to implement my own getter and setter and I'm not going to use instance variable.
Reason:
The reason is that I don't want to have memory overhead, as data is going to be stored in plain bytes archive. At the same time I don't want users to know implementation issues and keep interface signature unchanged.
#implementation MyObject {
NSData *_data
{
- (NSArray *)values
{
// Generate NSArray from _data
}
- (void)setValues(NSArray *)values
{
// Set _data from values
}
#pragma mark - Hidden init
- (id)initWithData:(NSData *)data
{
// Set _data
}
#end
If you implement both getter and setter yourself, instance variables are not synthesized.
As others said - if you override the setter and getter - the compiler does't do anything else. So what you want.. is what you have typed out.
If you dont wantbto create just create only instance variable.
#interface MyObject : NSObjet
{
NSArray *values;
}
#end
Eg:
//Myclass.h
#property(nonatomic, strong) NSString *name;
//MyClass.m
//#synthesize name = _name
So I know that we don't need to use #synthesize any more from iOS6+. The compiler automatically creates getters and setters for me.
But I don't understand is when to use self.name = #"Testing" and when to use _name = #"Testing"?
Should _name = #"Testing" be ever used?
If yes, when? When should an iVAR be used at all?
Also if i want to write my own getter and setter do i need to write #synthesize or can i just write my getter and setter?
Thanks for your help!
Normally, you only use instance variables in init methods, getters and setters, and dealloc. There are exceptions of course, but this is a good rule of thumb.
If you write both your own getter and setter (or in the case of a readonly property and you write the getter), you have to synthesize your property yourself. In all other cases, the property is auto-synthesized.
I tried to assign a value to recordingStatus -
ie recordingStatus = 1
But it doesn't go into the setter which i want some custom code.. what's wrong with my code?
Thanks.
Pier.
In file.h
#property (strong, nonatomic) IBOutlet UILabel *recordingStatusText;
#property (nonatomic)int recordingStatus;
....
In file.m
/* -------------------- Property Setter and Getters ----------------------*/
#synthesize recordingStatus;
- (int) getRecordingStatus {
return recordingStatus;
}
- (void) setRecordingStatus:(int)status
{
[_recordingStatusText setText: #"Just testing!"];
recordingStatus = status;
}
To set and get your property, you should use self.property = newValue;.
OVERRIDING SETTERS AND GETTERS
For getters you don't need to write 'get' in the method signature. So, your getter method uses the wrong name. If you want to override it, the method should be
-(int) recordingStatus {
// Custom Getter Method
return _recordingStatus;
}
In the case of ints, Objective-c wants to see your setter and getter methods in the format of
-(void)setValue:(int)newValue;
-(int)value;
Can you show the code where you call the setter? I'm assuming you're accessing the ivar directly by doing something like this (assuming your ivar is named recordingStatus):
recordingStatus = 1
Instead try this:
self.recordingStatus = 1