Objective C - changing a local variable w/ setter and w/o setter [duplicate] - objective-c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between self.ivar and ivar?
In Objective-C, what's the difference between [self setVariable: newStuff] and variable = newStuff?
When you have a class with a variable
#property (nonatomic) NSInteger num;
and you want to change the variable, typically you can do
[self setNum: newNum]
but you can also do
num = newNum
I know if you declare the variable readOnly, you can't use the first method to change it, but what's the concept behind it? Is it just because the second method with the setter can be called outside of its own class? Like if the class's instance was called 'sample'.
[sample setNum: newNum]
but then if you are changing the variable inside the class, either way is fine?

In Objective-C, what's the difference between [self setVariable:
newStuff] and variable = newStuff?
To be absolutely pedantic, one of them assigns the variable property the value in newStuff, whereas the other one assigns the value of newStuff to the iVar variable, but what I think you had in mind was a comparison between [self setVariable:
newStuff] and self.variable = newStuff. In that case, nothing is different, the compiler will expand case 2 out to case 1.
I know if you declare the variable readOnly, you can't use the first
method to change it, but what's the concept behind it? Is it just
because the second method with the setter can be called outside of its
own class? Like if the class's instance was called 'sample'.
readonly variables are important in cases where certain properties are private to the implementation of a class, but should be visible to other classes.
For example, if I were writing a Stack, I might want to expose the count of the number of items on the stack, but it would be a very bad idea for other classes to be able to write to the count variable. If I weren't smart and were using something like a count variable, I would want to be able to adjust the count of the semaphore internally (meaning you need it to be internally readwrite), so I declare a visibly readonly property so other classes can get it, but declare it internally readwrite so I can modify it:
//.h
#interface CFExampleStack : NSObject
#property (nonatomic, assign, readonly) int count; //readonly
#end
//.m
#interface CFExampleStack ()
#property (nonatomic, assign) int count; //readwrite
#end

Is it just because the second method with the setter can be called outside of its own class?
Well, that depends on how your instance variable is declared. By default, instance variables are #protected, i. e. they can be accessed from within the class and its subclasses only. However, if you explicitly declare an ivar as #public, then you can access it outside the class, using the C struct pointer member operator ->:
obj->publicIvar = 42;
However, this is not recommended, since it violates encapsulation.
Furthermore, if you use a custom setter method, then you have the opportunity to do custom actions when a property of an instance is updated. For example, if one changes the backgroundColor property of a UIView, it needs to redraw itself in addition to assigning the new UIColor object to its appropriate ivar, and for that, a custom setter implementation with side effects is needed.
Additionally, there are retained ("strong") and copied properties in case of instance variables that hold object. While writing a setter for a primitive type such as an integer is as simple as
- (void)setFoo:(int)newFoo
{
_foo = newFoo;
}
then, in contrast, a retained or copied property needs proper memory nanagement calls:
- (void)setBar:(Bar *)newBar
{
if (_bar != newBar) {
[_bar release];
_bar = [newBar retain]; // or copy
}
}
Without such an implementation, no reference counting would take place, so the assigned object could either be prematurely deallocated or leaked.

One more important difference...
Whenever you use self.prop KVC comes into play and you can observe the changes in the object, while _prop bypasses it.

Related

Most efficient way to have a publicly immutable, read-only array property that is privately mutable in Objective-C? [duplicate]

This question already has answers here:
How to declare an immutable property backed by a mutable type?
(3 answers)
Closed 8 years ago.
I recently got into a minor (but not unfriendly) disagreement in the comments on this question about how best to implement a read-only, immutable array property with underlying mutable storage in Objective-C. (The comments have since been moved to chat.)
First, let me be clear about what I want.
I want a property that is read-only, i.e., it is not assignable. myObject.array = anotherArray should fail.
I want the type of that property to be immutable so that new elements cannot be added to it through the property itself. Clearly, this means the type of the property should be NSArray.
I want the storage (i.e., the ivar) for that property to be mutable, because I will provide methods on the containing class to mutate it.
Since it seems not to be clear to some, let me stress that this question is about the frogs property of FrogBox class below, nothing more and nothing less.
I'll use the same contrived example from the linked question, a box of frogs, called FrogBox:
#interface FrogBox : NSObject
#property (nonatomic, readonly) NSArray *frogs;
- (void)addFrog:(Frog*)frog;
- (void)removeFrog:(Frog*)frog;
#end
#implementation FrogBox {
NSMutableArray *_frogs;
}
#dynamic frogs;
- (instancetype)init {
self = [super init];
if (self) {
_frogs = [NSMutableArray array];
}
return self;
}
- (NSArray*)frogs {
return _frogs;
}
- (void)addFrog:(Frog*)frog {
[_frogs addObject:frog];
}
- (void)removeFrog:(Frog*)frog {
// Frog implements isEqual and hash.
[_frogs removeObject:frog];
}
#end
Now, let's get something out of the way. The #dynamic directive is not strictly necessary here. Using #dynamic suppresses automatic synthesis of an ivar for the frogs property. Of course, if automatic synthesis sees an ivar with the same name as what it would have created, it just uses the supplied one. So why do I use it? I think it adds clarity and signals intent. If you don't like it, just imagine it's not there. It's not germane to the question.
The question is not about whether it's a good idea to want a publicly readonly, immutable and privately mutable property or not. It's about whether this is the most efficient way (in terms of syntax and clock cycles) to achieve that goal. I believe that it is, but I'd like to hear from the community, and am perfectly open to having my mind changed.
I want a property that is read-only, i.e., it is not assignable. myObject.array = anotherArray should fail.
I want the type of that property to be immutable so that new elements cannot be added to it through the property itself. Clearly, this means the type of the property should be NSArray.
I want the storage (i.e., the ivar) for that property to be mutable, because I will provide methods on the containing class to mutate it.
Well, I'm going to give the same answer I gave in the comments on the other question. What I do is:
Declare the property a readonly copy NSArray property in the public interface. This takes care of your 1 and 2; this thing now cannot be written to and it's an immutable array.
Redeclare the property readwrite privately in the .m file. Now I have to right to assign to it from within this class. To implement a mutating method, I read with mutableCopy, call an NSMutableArray method, and set - thus getting an immutable NSArray again automatically. Despite the use of the word "copy" there is actually no overhead.

difference between a variable with and without an underscore in objective-c [duplicate]

This question already has answers here:
How does an underscore in front of a variable in a cocoa objective-c class work?
(9 answers)
Closed 9 years ago.
In the tutorial i am following, it creates a property of an array like so
#property (nonatomic, retain) NSMutableArray *entries;
And in the implementation file and defines it defines it as...
entries = [[NSMutableArray alloc] init];
However in my program, defining like that gives me an error
"Use of undeclared identifier 'entries'; did you mean '_entries'?"
Does this affect my program?
In simple:
#property (nonatomic, retain) NSMutableArray *entries;
creates the following code for you:
An ivar called _entries and two methods
- (void)setEntries:(NSMutableArray *)entries;
- (NSMutableArray *)entries;
If you want to give the ivar a different name (e. g. entries without underscore) you have to synthesize them. But you hardly ever need the actual, just use your properties like self.entries.
The rare cases where you actually want the ivar is when you want to override the setter and getter method
- (void)setEntries:(NSMutableArray *)entries
{
_entries = entries;
// do more stuff
}
When you declare property compilator create private variable which you can access with underscore (_entries) and compilator also create setter (if you do not specify readonly) and getter. You can call getter in two ways:
[self entries] or self.entries
When you declare property you should access in it two ways:
_entries - You access your private variable directly (can be use just inside the class)
self.entries - You can access this property view setter/getter it's safe way because this method manage way how to access it (release, retain, copy, etc.)
#property (nonatomic, retain) NSMutableArray *entries; is nothing but an instance variable of name _entries. (or any other name, that you can specify while doing the synthesize)
When you do #synthesize entries, two accessor methods (setter and getter) are created for you
- (void)setEntries:(NSMutableArray *)entries;
- (NSMutableArray *)entries;
If you access it directly as _entries, then it is just changing the value of the variable.
But if you say self.entries, the accessor methods are called. The accessor methods are made according to what property type you specified, strong (or retain) copy assign atomic, say assign will just copy the value to the variable, atomic makes sure that if setter and getter are called together from different threads, getter always gets the value either prior to the start of setter or after the completion of setter.

How to prevent a variable from being created for a non-physical property in Objective-C? [duplicate]

This question already has answers here:
Declaring a property with no instance variable
(2 answers)
Closed 9 years ago.
In modern versions of Xcode, variables are automatically created to back properties. For example, #property (nonatomic, assign) BOOL isOpen would automatically create BOOL _isOpen. Is there a way to prevent such variables from being created when the property is meant to be non-physical? In the following example of a non-physical isOpen property, _isOpen is not needed. It is actually detrimental, because I've had co-workers inadvertdently use _isOpen and wonder why nothing would happen.
- (void) setIsOpen:(BOOL)isOpen
{
if (isOpen) {
[self.specialView open]
} else {
[self.specialView close];
}
}
- (BOOL) isOpen
{
return self.specialView.alpha > 0.0;
}
If you implement both the setter & the getter the variable will not be created. From Apple's docs:
The compiler will automatically synthesize an instance variable in all situations where it’s also synthesizing at least one accessor method. If you implement both a getter and a setter for a readwrite property, or a getter for a readonly property, the compiler will assume that you are taking control over the property implementation and won’t synthesize an instance variable automatically.
Your co-workers should not be able to reference _isOpen at all. I've checked your code in Xcode 4.6.3 and it behaves as per spec - no variable is created.
You need to specify both the getter and the setter. Assuming you do that, no instance variable is created.
Note that you can specify a different name for the getter, too. For boolean properties, the is prefix is usually dropped, though in the case of "open" I might leave it. I think it's clearer with the prefix.
For other boolean properties, though, something like this might be preferred:
#property (nonatomic, assign, getter=isOpen) BOOL open;
Then:
implement setOpen and isOpen.
read using BOOL value = object.open or BOOL value = [object isOpen]
write using object.open = value or [object setOpen:value].
Using #dynamic is not necessary; the recent compiler will detect you've specified both the getter and setter. #synthesize should not be necessary either. (There are a few edge cases; if you run into a case where it is necessary, by all means use it there).
Note, however, that I'm talking about the modern runtime here. 32-bit OSX targets use the legacy runtime, which has different rules.

Dot notation - property / method

Sanity check. Given this:
#property (readwrite, nonatomic) NSDate *start;
Then aren't these 2 lines of code identical?
Version 1:
self.start.description
Version 2:
[self.start description]
i.e. start.description calls the description method on the start object.
Yes, they're identical, and so is [[self start] description]
Basically yes.
Around the property there is a setter and getter autosynchoronizsed. In the event that you use an #syncronize statement then you have a chance to influence how the setter, getter and property are named. If you autosynchronize the property's name is _start. The getter name is start and the setter name is setStart.
So
something = self.start
actually calls the getter and
self.start = something
calls the setter.
Equivalents are:
something = [self start];
[self setStart:something];
If you ever want to access the instance variable directly then do so by:
_start = something;
something = _start;
In the event that you just use #synthesize start; then the equivalent would be:
start = something;
something = start;
That may well be confusing but start actually addresses the instance variable while self.start uses the setter/getter. This difference comes to vast importance when you do not ARC. Depending on the property parameters (e.g. assign, copy, retain, ...) the automatically generated getter and setter does some memeory management for you while the memory management is left to you when you work directly with the instance variable.
Yes. The result will be identical in both cases; properties are (mostly) just sugar around accessor methods written in the conventional Cocoa style.
I say "mostly" because there are some minor internal differences. Properties are added as meta-data to the runtime description of the Objective C class. You can, via some reflection, find out a list of properties that have been declared as such. This list is different from a list of methods that are named in the style of getter/setters.

Difference between properties and variables in iOS header file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a difference between an “instance variable” and a “property” in Objective-c?
Difference between self.ivar and ivar?
What is the difference between declaring variables in brackets immediately after the #interface line, and defining properties below?
For example...
#interface GCTurnBasedMatchHelper : NSObject {
BOOL gameCenterAvailable;
BOOL userAuthenticated;
}
#property (assign, readonly) BOOL gameCenterAvailable;
Defining the variables in the brackets simply declares them instance variables.
Declaring (and synthesizing) a property generates getters and setters for the instance variable, according to the criteria within the parenthesis. This is particularly important in Objective-C because it is often by way of getters and setters that memory is managed (e.g., when a value is assigned to an ivar, it is by way of the setter that the object assigned is retained and ultimately released). Beyond a memory management strategy, the practice also promotes encapsulation and reduces the amount of trivial code that would otherwise be required.
It is very common to declare an ivar in brackets and then an associated property (as in your example), but that isn't strictly necessary. Defining the property and synthesizing is all that's required, because synthesizing the property implicitly also creates an ivar.
The approach currently suggested by Apple (in templates) is:
Define property in header file, e.g.:
#property (assign, readonly) gameCenter;
Then synthesize & declare ivar in implementation:
#synthesize gameCenter = __gameCenter;
The last line synthesizes the gameCenter property and asserts that whatever value is assigned to the property will be stored in the __gameCenter ivar. Again, this isn't necessary, but by defining the ivar next to the synthesizer, you are reducing the locations where you have to type the name of the ivar while still explicitly naming it.
{
BOOL gameCenterAvailable;
BOOL userAuthenticated;
}
the above two are called member Variables
They can't be accessed outside the class.(Important point) (unless you provide custom getters and setters)
if you make a #property then the variable can be read inside the class as well as outside the class..so the setters and getters are generated for you..automatically
then declaring the same as a member variable isn't required..
It is just done to increase Readability .. you can read it easily than reading
#property (non..)
When you define a property a getter and setter is created for you. When you access them usingobject.member setters and getters are called automatically.
When you declare variable in interface setters and getters are not written for you. you can also specify some visibility modifiers to them like #private,#public etc.