Sorry for the kind of useless post title, but since I'm not really sure what I am doing, that was the best i could come up with.
In my header file it looks like this
#interface RootViewController : UITableViewController {
NSMutableArray *eventsArray;
}
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
This is not all the properties but i removed all but one for simplicity.
I'm doing this by following a guide from apple developer. It seems as though the guide is not totally updated since it tells me to synthesize properties, wich i should not have to anymore right?
Anyways, why is it like this? To me, a beginner at this, it seems as though I declare the property twice? Or do I do something else at the first row there?
It's like this for historical reasons, with the older compiler.
You can do this nowadays:
#interface RootViewController : UITableViewController
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
The way you have it, you are declaring an instance attribute, and then you are saying you want to automatically generate getters and setters.
Nowadays, you can just say you have a property and the compiler will automatically generate the instance attribute at compile time. It removes the apparent redundancy.
To me, a beginner at this, it seems as though I declare the property
twice? Or do I do something else at the first row there?
A property and the instance variable that backs it up (if there is one) are two different things. A property is really just a promise that the class provides certain accessor methods. So the fact that you had to declare the property and ivar separately isn't strange. However, most properties are, in fact, backed by an ivar with a related name, and writing and maintaining the two separately got to be a chore. So Apple added ivar synthesis to the compiler, so that the compiler generates an ivar for any synthesized properties for which an ivar doesn't already exist. Also, because synthesized accessors are by far the most common, and because the compiler will use any accessors that you provide even if a property is marked #synthesize, that became the default so that you no longer need the compiler directive.
Related
I have been unable to find any information on this topic and most of what I know about it has come by complete accident (and a few hours of trying to figure out why my code wasn't working). While learning objective-c most tutorials I have found make variables and properties with the same name. I don't understand the significance because it seems that the property does all the work and the variable just kind of sits there. For instance:
Test.h
#interface Test : NSObject {
int _timesPlayed, _highscore;
}
#property int timesPlayed, highscore;
// Methods and stuff
#end
Test.m
#implementation Test
#synthesize timesPlayed = _timesPlayed;
#synthesize highscore = _highscore;
// methods and stuff
#end
What I know
1) Okay so today I found out (after hours of confusion) that no matter how much changing you do to the properties highscore = 5091231 it won't change anything when you try to call [test highscore] as it will still be returning the value of _highscore which (I think) is the ivar that was set in test.h. So all changing of variables in test.m needs to be changing _highscore and not highscore. (Correct me if I'm wrong here please)
2) If I understand it correctly (I probably don't) the ivars set in test.h represent the actual memory where as the #properties are just ways to access that memory. So outside of the implementation I can't access _highscore without going through the property.
What I don't understand
Basically what I don't get about this situation is whether or not I need to use the ivars at all or if I can just use #property and #synthesize. It seems like the ivars are just extra code that don't really do anything but confuse me. Some of the most recent tuts I've seen don't seem to use ivars but then some do. So is this just a coding preference thing or is it actually important? I have tried searching through Apple's Documentation but I get rather lost in there and never seem to find what I'm looking for. Any guidance will be greatly appreciated.
You can think of the syntax for synthesizing properties as #synthesize propertyName = variableName.
This means that if you write #synthesize highscore = _highscore; a new ivar with the name _highscore will be created for you. So if you wanted to you could access the variable that the property is stored in directly by going to the _highscore variable.
Some background
Prior to some version of the compiler that I don't remember the synthesis statement didn't create the ivar. Instead it only said what variable it should use so you had to declare both the variable and the property. If you synthesized with a underscore prefix then your variable needed to have the same prefix. Now you don't have to create the variable yourself anymore, instead a variable with the variableName that you specified in the synthesis statement will be created (if you didn't already declare it yourself in which case it is just used as the backing variable of the property).
What your code is doing
You are explicitly creating one ivar called highscore when declaring the variable and then implicitly creating another ivar called _highscore when synthesizing the property. These are not the same variable so changing one of them changes nothing about the other.
Should you use variables or not?
This is really a question about preference.
Pro variables
Some people feel that the code becomes cleaner if you don't have to write self. all over the place. People also say that it is faster since it doesn't require a method call (though it is probably never ever going to have a measurable effect on your apps performance).
Pro properties
Changing the value of the property will call all the necessary KVO methods so that other classes can get notified when the value changes. By default access to properties is also atomic (cannot be accessed from more then one thread) so the property is safer to read and write to from multiple thread (this doesn't mean that the object that the property points to is thread safe, if it's an mutable array then multiple thread can still break things really bad, it will only prevent two threads from setting the property to different things).
You can just use #property and #synthesize without declaring the ivars, as you suggested. The problem above is that your #synthesize mapped the property name to a new ivar that is generated by the compiler. So, for all intents and purposes, your class definition is now:
#interface Test : NSObject {
int timesPlayed;
int highscore;
int _timesPlayed;
int _highscore;
}
...
#end
Assigning a value directly to the ivar timesPlayed will never show up if you access it via self.timesPlayed since you didn't modify the correct ivar.
You have several choices:
1 Remove the two ivars you declared in your original post and just let the #property / #synthesize dynamic duo do their thing.
2 Change your two ivars to be prefixed by an underscore '_'
3 Change your #synthesize statements to be:
#implemenation Test
#synthesize timesPlayed;
#synthesize highscore;
...
I typically just use #property and #synthenize.
#property gives the compiler and the user directions on how to use your property. weather it has a setter, what that setter is. What type of value it expects and returns. These instructions are then used by the autocomplete (and ultimately the code that will compile against the class) and by the #synthesize
#synthesize will by default create an instance variable with the same name as your property (this can get confusing)
I typically do the following
#synthesize propertyItem = _propertyItem;
this will by default create a getter and a setter and handle the autorelease as well as create the instance variable. The instance variable it uses is _propertyItem. if you want to access the instance variable you can use it as such.
_propertyItem = #"Blah";
this is a mistake tho. You should always use the getter and setter. this will let the app release and renew as needed.
self.propertyItem = #"Blah";
This is the better way to handle it. And the reason for using the = _propertyItem section of synthesize is so you cannot do the following.
propertyItem = #"Blah"; // this will not work.
it will recommend you replace it with _propertyItem. but you should use self.propertyItem instead.
I hope that information helps.
In your example, #synthesize timesPlayed = _timesPlayed; creates a new ivar called _timesPlayed and the property refers to that ivar. timesPlayed will be an entirely separate variable with no relation whatsoever to the property. If you just use #synthesize timesPlayed; then the property will refer to timesPlayed.
The purpose of the underscore convention is to make it easier to avoid accidentally assigning directly to an ivar when you want to be doing it through the property (i.e. through the synthesized setter method). However, you can still acces _timesPlayed directly if you really want to. Synthesizing a property simply auto-generates a getter and setter for the ivar.
In general you do not need to declare an ivar for a property, although there may be special cases where you would want to.
This may be an old question.. but in "modern times", #synthesize- is NOT necessary.
#interface SomeClass : NSObject
#property NSString * autoIvar;
#end
#implementation SomeClass
- (id) init { return self = super.init ? _autoIvar = #"YAY!", self : nil; }
#end
The _underscored backing ivar IS synthesized automatically... and is available within THIS class' implementation, directly (ie. without calling self / calling the automatically generated accessors).
You only need to synthesize it if you want to support subclass' ability to access the _backingIvar (without calling self), or for myriad other reasons, described elsewhere.
I recently came across this formatting for a .h header file. Can someone explain to me why this is done this way and what it means? In particular, I am confused about what is in the first set of braces/the repetition? How does this differ from if I were to delete the braces and everything between them?
#interface ACustomView : UIView
{
float chartWidth, chartHeight;
}
#property (nonatomic, readwrite) float chartWidth, chartHeight;
#end
How does this differ from if I were to delete the braces and everything between them?
A #property, of itself, is just a method declaration (or, in your case, two method declarations, a getter and a setter). Typically, you want those methods to be backed by actual instance variable which the getter and setter will get and set. That is what is declared in the curly braces.
Deleting the instance variable declarations in your code doesn't change very much, however, because the compiler will use your #property declaration to autosynthesize instance variables for you. In other words, you typically need instance variables backing a #property, but you don't need to declare them explicitly.
In your particular code, however, you have not shown enough information to reveal what's really going on. A lot depends on what you do (or don't do) in the corresponding .m file. If you say #synthesize for this #property, what is synthesized will be these instance variables, chartWidth and chartHeight. But if you don't say #synthesize, you'll get autosynthesis of instance variables _chartWidth and _chartHeight, and so now, if you also declare chartWidth and chartHeight instance variables explicitly, you'll have something of a mess on your hands.
When creating a class, a BOOL property declaration often looks like this:
#property (nonatomic, getter=isActive) BOOL active;
For normal classes and subclasses, naming the getter is<#Key#> makes sense, looks sharp, and is nice to use in if statements.
What about when naming properties in a category though?
I was just implementing some helper methods on NSView, when all of the sudden, things took a hideous turn:
#property (nonatomic, readonly, getter=bsd_isFieldEditorDelegate) BOOL bsd_fieldEditorDelegate;
After adding the recommended prefix (bsd_ in my case), the semantic value of the getter variation seems to get lost. In this case, should I just remove the getter name altogether or what?
I looked throughout the documentation, but I couldn't find a definitive answer. Is there one, or am I just overthinking it?
You CANNOT use property in Category of Objective-C. Instead of, you should use Associated object of Objective-C Runtime. Because of that, attribute of property is may not work with Associated object.
Reference: Objective-C: Property / instance variable in category
In iOS 8 NSManagedObject was given a new property:
#property (nonatomic, getter=isDeleted, readonly) BOOL deleted;
Unfortunately, I have already been using a property of the same name in my subclasses of NSManagedObject to mark objects as soft deleted.
#property (nonatomic, retain) NSNumber *deleted; // BOOL in CoreData model
This results in a ton of compiler warnings:
'getter' attribute on property 'deleted' does not match the property inherited from 'NSManagedObject'
How does Objective-C handle a superclass and subclass having the same property? I obviously plan on renaming this property across the board but there is already multiple versions of this app in the wild and I am curious of the implications.
#property accessors are just regular methods, so they're handled exactly the same way as other methods. In this case, I believe you luck out because the framework (NSManagedObject) getter is -isDeleted rather than -deleted. Since your subclass implements -deleted, there's technically no conflict with the getter.
Now, the real issue will be, if NSManagedObject internally implements the corresponding -setDeleted: setter, your subclasses implementation of that method will be called instead of NSManagedObject's implementation. A quick check using -instancesRespondToSelector: seems to reveal that NSManagedObject does not actually implement -setDeleted: (on OS X, anyway). So, you might be OK.
The actual implications of a conflict like this for your app (assuming a case where you weren't lucky as described above) are not clear to me, not knowing exactly what your app is doing or why. For what it's worth, the -isDeleted method on NSManagedObject is not at all new. It was simply promoted to a declared #property in iOS 8 (presumably to ease Swift interoperability). It was probably always a bad idea to have your own deleted property...
This question already has answers here:
Do declared properties require a corresponding instance variable?
(6 answers)
Closed 8 years ago.
For example, in the following codes.
#interface TUTViewController : UIViewController
{
NSTimer *timer;
}
#end
and
#interface TUTViewController : UIViewController
#property (weak, nonatomic) NSTimer *timer;
#end
In which scenario do we use the first method to declare variable?
You are going to get lots of opinions on this, often stated as hard fast rules.
Example:
Maddy: Never put ivars in the .h. ivars should always be private
meaning they do not belong in the public .h. If you create ivars, put
them in the .m file
I have tremendous respect for Maddy, but I disagree with him on this one.
If you put your iVars in your .m file, they are hidden from other classes, but they are also hidden from subclasses that you create.
I prefer to mark my instance variables as #protected, which makes them available to subclasses, but not to other classes.
Others will tell you to make EVERYTHING a property. Before ARC, it made sense to save all your objects in properties, since you could use the setter on the property to manage the memory on your objects. (When assigning a value to a retained property, the setter would first release any old value, then retain the new value.) Now ARC takes care of that for you even for iVars, so the argument for making everything a property is less.
What I do is to make everything an iVar, unless:
I need a custom getter or setter method with special behavior.
I want to access the value from another object.
I need to mark a property as "atomic" for access from another thread. (get in the habit of declaring all of your properties as "nonatomic." If you don't know what atomic is for for, you want nonatomic. Atomic properties are slower than nonatomic.)
As a matter of policy I NEVER access another object's iVars except trough a property.
There is a small but real amount of overhead in using a property rather than an instance variable. A property read/write always makes a method call. An iVar accesses the memory directly without the overhead of a method call. Usually the difference is too small to matter. But, if you're doing millions of operations, like doing something to every pixel in a large image, or handling callbacks from processing video or audio samples in real-time, the difference can be large.
I would highly suggest to use #properties unless there is a very good reason not to. It's true the discussion is a religious one more than a technical one but since we are probably all followers of the Cult of Mac, if Apple prefers you to use #properties then that's the standard. In my opinion both Apple documentation and Xcode aren't as pushy on standards like ReSharper would do in Visual Studio for instance (it warns when you don't use var for example). That's a pity because that would make it easier for me to pick up code after somebody else.
There is a way to "hide" #properties in a .m file, you should declare it as follows:
#interface ABCMySpiffyClass ()
#property (weak, nonatomic) IBOutlet UIImageView *spiffyImage;
#property (weak, nonatomic) IBOutlet UILabel *spiffyTitle;
#end
These are not completely private to another consumer of your class but it is hidden at first sight. This should tell the other developer that he or she should not use them. I think public/private has more to do with documentation as it has to do with application security for most apps.