Difference between a property and a global variable [objective c] - objective-c

I'm wondering what the difference between a class's public global variable and a class's property is (Objective-C primarily iOS programming). Only thing I notice is that you have to use pointer notation -> to access a class's global variable rather than a dot.
I've read that changing code from using globals to using properties can be a program breaking change. Is that true and if so, why?
Thanks!
Edit:
Block.h
Public Global Variable (I think?) [Edit: I now understand this is an Instance Variable, thanks]
#interface Block : GameObject {
#public
int type;
SKEmitterNode *particles;}
Property
#property (nonatomic) CGFloat x;

No, this is not a "global variable".
It is called an instance variable.
A property often (but not necessarily) has an associated instance variable, but the modern compilers hide that from you.
The big difference between using an instance variable is, that a property is always accessed through its accessors (in your case setX:(CGFLoat)x?and -(CGFloat)x`.
If you wanted, you could overwrite these accessors and do special handling, say, whenever the variable is accessed.
It is always possible to bypass the accessors by using the instance variable directly. In a case of an auto-synthesized iVar, this would be _x.
Note that the -> is not necessary in either case

Even a class property is backed by a class variable even though it is not global.
But with a property one has additional gatekeepers guarding access to the variable:
You can make the property readonly.
Finetune memory semantics (copy, assign, etc).
By using KVO it is easy to let changes propagate automatically.

Related

Define instance Variables without property

I know that it is possible in Objective C to define an instance variable without a property when I use curly braces in the top of the interface or the implementation. But what is the advantage when I do that?
I think your question should be comparing to property what is the advantage of defining instance variables.
Most property is backed by a instance variables. By default, a readwrite property will be backed by an instance variable, which will be synthesized automatically by the compiler. (A readonly property won't synthesize an instance variable, it only synthesizes a getter method which a readwrite property synthesize an instance variable and a getter and a setter method)
So property provides methods that synthesized by compiler to access the instance variable. I can't say which one has any advantages, just use the one which is proper to your case.
You may need to learn more about property. Properties Encapsulate an Object’s Values
The most advantage is this variables actually can be private/protected/public members according to the keyword (#private/#protected/#public) you set.
Take a look at this question

self.variableName vs. _variableName vs. #sysnthesize variableName [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
Note: For the folks digging around trying to understand this, I figured-out the source of my confusion. In the .h, I had:
...
#interface myClass : parentClass {
className *variableName:
}
#property (strong, nonatomic) className *variableName;
...
This leads to self.variableName and _variableName being two distinct variables in the .m. What I needed was:
...
#interface myClass : parentClass {
className *_variableName:
}
#property (strong, nonatomic) className *variableName;
...
Then, in the class' .m, self.variableName and _variableName are equivalent
In brand-new, Xcode 4.5+, with ARC, targeting iOS 5.0+ project, is there a distinct advantage (runtime efficiency, speed, etc.) to using _variableName over self.variableName vs. the old-style #synthesize variableName?
My understanding is that Xcode 4.5+ will create a default accessor _variableName that is equivalent to self.variableName and the only reasons not to use #synthesize variableName is to avoid confusion between iVars and passed-in variables, correct?
To me, just using self.variableName to access an iVar seems the most straightforward and clear as to which variable you're looking for. Other than typing _ vs. self., is there an advantage to using _variableName?
My understanding is that Xcode 4.5+ will create a default accessor "_variableName" that is equivalent to self.variableName and the only reasons not to use "#synthesize variableName" is to avoid confusion between iVars and passed-in variables, correct?
In this case, _variableName isn't the accessor, it's an ivar that is automatically generated by the compiler and used in the automatically #synthesized setters and getters. Generally, it is considered best to use accessors whenever possible (i.e. self.variableName) so that things like key-value observation and bindings work for that property.
When you access an ivar directly, it is accessed via direct memory access, the same way you would access data in a struct. It simply takes the pointer for the object that owns the ivar, offsets the memory address and attempts to read or write to the memory at that location. Using dot notation (self.variableName) calls the accessor methods to set or get that property and can do a number of different things along the way, such as:
1) Locking: If the property is going to be used in multiple threads and is an atomic property, the runtime will automatically do some locking to make sure that the property is not accessed at the same time from multiple threads. If your object is not meant to be used on multiple threads, you can give the nonatomic hint in your property declaration so that the synthesized accessors skip the locking.
2) Key-Value Notifications: The default setters for properties call -willChangeValueForKey: and -didChangeValueForKey:, which sends out notifications when the property is changed. This is necessary for anything to update properly if bindings are used, and for any other key-value observation.
3) Custom accessor behavior: If you end up writing your own setters and getters, any custom stuff that you implement within those.
Technically, accessing the ivar directly is faster than using accessors, but there are very few situations in which it will make a significant performance difference, and would probably be a case of premature optimization. Even if you don't feel like you would be using the benefits listed above right away, it's probably better to use the accessors anyway so that if you decide later on you need some of that functionality, you don't have to change every instance of accessing that variable (and possibly be creating unexpected new bugs in the process).
In addition, if you are accessing ivars directly and end up refactoring your class into categories or subclasses, it gets messy because you usually have to declare the ivar as a #protected variable. You wouldn't have to do this if you are using the accessors.
Generally, I try to only access the ivars directly in init, dealloc, and the property's accessor. A lot of engineers go by this rule of thumb because sometimes the custom stuff that happens in accessors can cause unexpected behavior while the object is init'ing or dealloc'ing. For example, if anything in the accessors causes something to retain or release your object or even form a zeroing weak reference to it, it will cause a crash if used in dealloc.
In the latest Xcode #synthesize is optional. By default, omitting #synthesize is the same as writing
#synthesize someName = _someName;
The only reason to use #synthesize is to rename the instance variable created to store the value of the property, for example
#synthesize someName = someSpecialName;
When you use self.variableName to access a variable, you go through a property, which is a short method that accesses the instance variable for you. Although the method dispatch is very fast, it may perform additional services for you, such as synchronizing the access to the variable (this is the case when you specify atomic or do not specify nonatomic in the property declaration). In cases like that, the access through self.variableName will be somewhat slower. If done in a tight loop, this could potentially make a difference. That is why you sometimes want to access the underlying instance variable directly by using _variableName.

Why call "self.classVariable" when you can just call "classVariable"?

I understand that one version directly accesses the instance variable and the other calls it's accessor method.
If self.classVariable = sandwich;
&
If classVariable = sandwich;
do the same thing.
Can someone explain the point of the extra typing?
In Objective-C, self.property is property access, not direct instance variable access. It is syntatic sugar for [self property] or [self setProperty:], and thus has the semantics of a message. Modern Objective-C runtime can synthesize a backing instance variable (of the same name as the property), but you may back a property with an instance variable with a different name or none at all. In other words,
self.property = foo;
id bar = property
and
property = foo;
id bar = property;
are not at all the same thing.
It's generally a bad idea to mix direct and property access (with the exception that you should be accessing ivars directly in -init and -dealloc methods) because you will easily run afoul of memory management rules.
The extra typing is to protect the code from future changes, in case a variable is named (in scope) equal to the class member.
It is also considered good practice (in some circles) to include Self when referring to members in the class to be unambiguously clear where it comes from which in some ways helps quicken comprehension of the code.
For Objective-C specifically, there is another difference as noted here http://answers.oreilly.com/topic/1193-calling-self-object-rather-than-calling-the-object-directly-in-objective-c/
The SELF.X notation goes through the accessors generated by the #synthesize directive, whereas X directly bypasses them.
If you go through the accessor you can set breakpoints there. Handy sometimes. Also things like retain/copy properties won't work if you don't go through the accessor.

How does dot syntax work without explicit #property in Objective-C?

I wrote a setter and getter method following Apple's conventions and noticed that despite having no variable I can still access the setter and getter using the dot syntax. Is this normal behavior? What enables this feature?
Example:
// Header definition. Keep in mind there is no class variable or #property for height.
- (void)setHeight:(float)height;
- (float)height;
// else using the dot syntax.
object.height = 10.0f;
A property-access expression is equivalent to a message expression:
[object setTexture:tex];
A property declaration is equivalent to one (readonly) or two (readwrite/default) instance-method declarations. Keywords like retain tell the compiler how to implement the method if you tell it to do so (#synthesize).
However, you can skip the property declaration and declare the methods directly, as shown in your question. You can't synthesize their implementations, since you need a property declaration for that (otherwise, it wouldn't know what memory-management policy to use: assign, retain, or copy), but you can always implement the methods yourself.
Then, even though you declared and implemented the methods yourself, since property-access syntax and message syntax are equivalent to each other, you can use the methods whichever way you want: With a message expression, or with a property-access expression.
Some would consider it bad form, though, to use property access expressions on anything but a formal #property (e.g., myString.length or myArray.count or myView.frame). It definitely is bad form to use a property-access expression to send a message that doesn't access any kind of property; foo.retain.autorelease, for example, is bad and wrong: It reeks of trying to pretend you're programming some other language than Objective-C.
Incidentally, a property and a variable are unrelated. A #property will ordinarily be backed by an instance variable, but this is not required: You could store the property's value inside another object, or convert it to and from some other format, or both. Likewise, accessing a property (which is an accessor message) and accessing an instance variable (which is just accessing a variable, nothing more) are very different.

Using instance variables with Modern Runtime

I have several years of experience in Obj-c and Cocoa, but am just now getting back into it and the advances of Obj-C 2.0 etc.
I'm trying to get my head around the modern runtime and declaring properties, etc. One thing that confuses me a bit is the ability in the modern runtime to have the iVars created implicitly. And of course this implies that in your code you should always be using self.property to access the value.
However, in init* and dealloc(assuming you're not using GC) methods we should be using the iVar directly (in the current runtime).
So questions are:
Should we use property accessors in init* and dealloc with Modern Runtime?
If so, why is this different? Is it just because the compiler can't see the iVar?
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
I read the docs several times, but they seemed a bit vague about all of this and I want to be sure that I understand it well in order to decide how I want to continue coding.
Hope that my questions are clear.
Quick summary of testing:
If you don't declare the ivar in legacy, compiler is completely unhappy
If you use #ifndef __OBJC2__ around ivar in legacy compiler is happy and you can use both ivar directly and as property
In modern runtime, you can leave the ivar undefined and access as property
In modern runtime, trying to access ivar directly without declaration gives error during compile
#private declaration of ivar, of course, allows direct access to ivar, in both legacy and modern
Doesn't really give a clean way to go forward right now does it?
In the current (OS X 10.5/GCC 4.0.1) compiler, you cannot directly access the runtime-synthesized ivars. Greg Parker, one of the OS X runtime engineers put it this way on the cocoa-dev list (March 12, 2009):
You can't in the current compiler. A
future compiler should fix that. Use
explicit #private ivars in the
meantime. An #private ivar should not
be considered part of the contract -
that's what #private means, enforced
by compiler warnings and linker
errors.
And why isn't there a way to
explicitly declare instance variables
in the .m file for the new runtime?
Three reasons: (1) there are some
non-trivial design details to work
out, (2) compiler-engineer-hours are
limited, and (3) #private ivars are
generally good enough.
So, for now you must use dot-notation to access properties, even in init and dealloc. This goes against the best practice of using ivars directly in these cases, but there's no way around it. I find that the ease of using runtime-synthesized ivars (and the performance benefits) outweigh this in most cases. Where you do need to access the ivar directly, you can use a #private ivar as Greg Parker suggests (there's nothing that prevents you from mixing explicitly declared and runtime-synthesized ivars).
Update With OS X 10.6, the 64-bit runtime does allow direct access to the synthesized ivars via self->ivar.
Since instance variables themselves can only be synthesized in the modern runtime (and must be declared in the #interface under 32-bit or pre-Leopard), it's safest / most portable to also declare the ivar
Should we use property accessors in init* and dealloc with Modern Runtime?
My rule of thumb is "possibly" for -init*, and "usually not" for -dealloc.
When initializing an object, you want to make sure to properly copy/retain values for ivars. Unless the property's setter has some side effect that makes it inappropriate for initialization, definitely reuse the abstraction the property provides.
When deallocating an object, you want to release any ivar objects, but not store new ones. An easy way to do this is to set the property to nil (myObject.myIvar = nil), which basically calls [myObject setMyIvar:nil]. Since messages to nil are ignored, there is no danger in this. However, it's overkill when [myIvar release]; is usually all you need. In general, don't use the property (or directly, the setter) in situations where deallocation should behave differently than setting the variable.
I can understand eJames' argument against using property accessors in init/dealloc at all, but the flipside is that if you change the property behavior (for example, change from retain to copy, or just assign without retaining) and don't use it in init, or vice versa, the behavior can get out of sync too. If initializing and modifying an ivar should act the same, use the property accessor for both.
If so, why is this different? Is it just because the compiler can't see the ivar?
The modern runtime deals with class size and layout more intelligently, which is why you can change the layout of ivars without having to recompile subclasses. It is also able to infer the name and type of the ivar you want from the name and type of the corresponding property. The Objective-C 2.0 Runtime Programming Guide has more info, but again, I don't know how deeply the details explained there.
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
I haven't tested this, but I believe you're allowed to access the named ivar in code, since it actually does have to be created. I'm not sure whether the compiler will complain, but I would guess that since it will let you synthesize the ivar without complaining, it is also smart enough to know about the synthesized ivar and let you refer to it by name.
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
You should be able to access the property and/or ivar anytime after the instance has been allocated.
There is another SO question with similar information, but it isn't quite a duplicate.
The bottom line, from the Objective-C 2.0 documentation, and quoted from Mark Bessey's answer is as follows:
There are differences in the behavior that depend on the runtime (see also “Runtime Differences”):
For the legacy runtimes, instance variables must already be declared in the #interface block. If an instance variable of the same name and compatible type as the property exists, it is used—otherwise, you get a compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.
My understanding is as follows:
You should not use property accessors in init* and dealloc methods, for the same reasons that you should not use them in the legacy runtime: It leaves you open to potential errors if you later override the property methods, and end up doing something that shouldn't be done in init* or dealloc.
You should be able to both synthesize the ivar and override the property methods as follows:
#interface SomeClass
{
}
#property (assign) int someProperty;
#end
#implementation SomeClass
#synthesize someProperty; // this will synthesize the ivar
- (int)someProperty { NSLog(#"getter"); return someProperty; }
- (void)setSomeProperty:(int)newValue
{
NSLog(#"setter");
someProperty = newValue;
}
#end
Which leads me to think that you would be able to access the synthesized ivar in your init* and dealloc methods as well. The only gotcha I could think of is that the #synthesize line may have to come before the definitions of your init* and dealloc methods in the source file.
In the end, since having the ivars declared in the interface still works, that is still your safest bet.
I am running into the same problem. The way I am working around not being able to access the synthesized instance variables is the following:
public header
#interface MyObject:NSObject {
}
#property (retain) id instanceVar;
#property (retain) id customizedVar;
#end
private header / implementation
#interface MyObject()
#property (retain) id storedCustomizedVar;
#end
#implementation MyObject
#synthesize instanceVar, storedCustomizedVar;
#dynamic customizedVar;
- customizedVar {
if(!self.storedCustomizedVar) {
id newCustomizedVar;
//... do something
self.storedCustomizedVar= newCustomizedVar;
}
return self.storedCustomizedVar;
}
- (void) setCustomizedVar:aVar {
self.storedCustomizedVar=aVar;
}
#end
It's not that elegant, but at least it keeps my public header file clean.
If you use KVO you need to define customizedVar as dependent key of storedCustomizedVar.
I'm relatively new to Obj-C (but not to programming) and have also been confused by this topic.
The aspect that worries me is that it seems to be relatively easy to inadvertently use the iVar instead of the property. For example writing:
myProp = someObject;
instead of
self.myProp = someObject;
Admittedly this is "user" error, but it's still seems quite easy to do accidentally in some code, and for a retained or atomic property it could presumably lead to problems.
Ideally I'd prefer to be able to get the runtime to apply some pattern to the property name when generating any iVar. E.g. always prefix them with "_".
In practice at the moment I'm doing this manually - explicitly declaring my ivars, and deliberately giving them different names from the properties. I use an old-style 'm' prefix, so if my property is "myProp", my iVar will be "mMyProp". Then I use #synthesize myProp = mMyProp to associate the two.
This is a bit clumsy I admit, and a bit of extra typing, but it seems worth it to me to be able to disambiguate a little bit more clearly in the code. Of course I can still get it wrong and type mMyProp = someObject, but I'm hoping that the 'm' prefix will alert me to my error.
It would feel much nicer if I could just declare the property and let the compiler/runtime do the rest, but when I have lots of code my gut instinct tells me that I'll make mistakes that way if I still have to follow manual rules for init/dealloc.
Of course there are also plenty of other things I can also do wrong...