Need explanation on #property/#synthesize in iOS - ios

Not a complete noob I am quite new to iOS programming and to Ojbective-C. I mainly come from a background of C (DSP, Microcontrollers), Delphi XE2/Pascal , Visual Basic and Java (desktop and Android apps).
I mainly learned Cocoa with the book "Beginning iOS 5 Development", from Apress.
Recently I watched videos of the WWDC 2012 and went through some of their sample code, and I must say that I am confused of what is the proper way of writing my apps and more specifically with the #property/#synthesize words.
In the book most (not to say all) of the sample code uses to define a property as for example
ViewController.h
#property (strong, nonatomic) NSMutableArray *list;
ViewController.m
#synthesize list;
then all the code access synthesize list with
self.list
or even simply
list
Now in every WWDC code sample I read I see that programmers define a property but then, in the .m file they do things like
#synthesize list = _list;
and access sometimes
self.list
or
_list
I am confused. What is the correct practice ? As Apple programmers all use underscore I think I should do it that way but why the book did not ? Is there a difference between list and _list ? And more over, as I am in the same object why sometime use self.list and sometimes list/_list.
Sometimes they don't use #synthesize, I assume it's when they want to re-write their own accessors and mutators (which is never my case up to now).
I have read here and there on the web but nothing was clear enough to set my mind right, so I count on StackOverflow to bring light here.
Last but not least I prefer and answer based on current iOS 6 best practice/programming technique. Useless to tell me how to do it correctly in older iOS.

There is no correct way. There is only your preferred style.
The lastest compilers do an implicit synthesise on the property declaration.
#synthesize list = _list; .
Nothing is ever written in your code. It just happens.
However that doesnt stop you doing this explicitly.
#synthesize list = somethingelse;
So when you ask for a pointer to list via the accessor (self.list) you will get a pointer to somethingelse
In most cases NSMutableArray *thing = self.list is equivalent to NSMutableArray *thing = somethingelse
And just because Apple uses a style doesn't mean that you have to do it. Each company usually has their own coding style.
The main problem with using #synthesize list; is that it poses the risk that you can write either
self.list = thing or list = thing .
The former uses the sythesised setList: accessor while the latter doesn't and put the risk of related bugs in your code , though its not as bad with ARC as you dont get leaks happening for strong properties.
What ever style you use, keep it consistent and be aware of the effects of using an ivar directly list = thing as compared to using its accessor self.list = thing

This is a language feature that has had its usage evolve rapidly over the past few years, which explains the various forms. With the most recent tools, you can choose to ignore #synthesize and have things work reasonably.
The default behavior in that case produces the same effect as #synthesize list = _list;.

Related

iOS common objects

I'm writing an iOS app where there is a common object that all views within the app need to access.
I have been creating, and initialising the object within the viewDidLoad event (of the first view controller), and then passing a reference to this object to all other views that need it. This does not seem like the correct way to do things, feels like I'm somehow breaking the MVC pattern since I'm relying that this particular view is always the first to load in order to setup objects that the whole application needs.
I have now modified my app to do the basic object creation and initialisation in the appDelegate "didFinishLaunching...". This is now working and I can access this common object from all of my other views without having to pass around a reference from one view to the other.
Before I go and continue too far, I was hoping to get peoples input on whether this is the correct way to do things, or whether I should be doing anything else? Sorry if this seems like a trivial question, I'm just learning and want to learn how to do things properly.
Thanks in advance :-)
Without repeating what has already been answered, I'd suggest you make your own Singleton object to hold your 'globals', so you don't clutter your AppDelegate with it.
#interface MyGlobalDataController : NSObject
#property (nonatomic, strong) MyData *myData;
+(MyGlobalDataController *)sharedInstance;
#end
#implementation MyGlobalDataController
static MyGlobalDataController *MyGlobalDataControllerSharedInstance = nil;
- (id)init {
self = [super init];
if (self) {
// do whatever needs doing
}
return self;
}
+(MyGlobalDataController *)sharedInstance {
#synchronized(self) {
if (MyGlobalDataControllerSharedInstance == nil) {
MyGlobalDataControllerSharedInstance = [[MyGlobalDataController alloc] init];
}
}
return MyGlobalDataControllerSharedInstance;
}
#end
The first time you access your sharedInstance, the init will be called, so you don't have to worry about timing there.
Putting your global object initialisation in didFinishLaunching is a better idea than having it in didLoad.
Some people will disagree with me here and say you shouldn't have globals full stop, but personally I think having some sort of global state is acceptable. I love a good object-orientated app but there is a balance to be struck between solid OOP and the flexibility provided by having a few globals.
I think ultimately do whatever is right for you, the major disadvantage of having a global state is that it becomes difficult to maintain and has the potential to introduce a lot of bugs / unexpected behaviour especially in a large app, whereas if you stick to the MVC pattern then each view in your app simply does what it is meant to without unnecessarily affecting other parts of the app.
Nowadays, I tend to stick to MVC / OOP principles for the most part, but have an [AppDelegate]sharedAppDelegate] singleton I can use to access variables at certain points. I have very, very few variables in here but they do come in handy i.e. now my app has a shared 'loading HUD' which is managed by this class, and my sharedAppDelegate also contains a lot of static methods for initiating HTTP, parsing JSON etc which saves a lot of time.
One alternative to having global information in your appDelegate is using NSUserDefaults to store key-value information
Hope that helps anyway, like I said some people will disagree with me but ultimately it boils down to personal preferences, and where the balance for you in terms of rigidity to the MVC model versus flexibility is

Properties and ivars in MasterDetail template

After reading about properties and ivars in Objective C I'm still confused with MasterDetail template for iOS in XCode.
MasterViewController declares property for DetailViewController:
#class DetailViewController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
And ivar for array of objects:
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
Why is it that way? I just can't get why those two things are declared differently.
Thanks.
Declaring something as a "property" allows other objects to access and work with it. In The case above, adding "detailViewController" as a property to MasterViewController means other objects can access and work with the methods & properties DetailViewController exposes.
While the "_objects" variable is internal (or private) to the MasterViewController.
Apple's documentation is generally excellent. Apple's templates are... sometimes a little challenged. They are also sometimes slow to be updated as the language improves (or they are updated erratically). The objects array should really be a private property rather than an implementation-declared ivar. In any case, don't read too much into this.
Remember, the view controller shouldn't even be holding the data; it should be getting it from the model classes (which the template doesn't provide). Some of this is in order to keep the templates simpler to use (they're not actually example code; they're templates). Some of the weird code is due to limitations in the templating engine. (They didn't used to be able to prefix your classnames, even though they told you that you must prefix your classnames; it was very annoying.)
Unfortunately, seeing something in example code also doesn't necessarily mean it's a correct way to code. Much of Apple's example code would be completely inappropriate in production code (most of their examples lack proper model classes, or fail to handle errors correctly). But again, that's kind of the nature of example code. Focus on the coding guidelines. They're much more useful than learning from templates and examples.

"Proper" way to define a class - Properties vs Methods

This is an observation and a question:
I am loading some json data into a class (json already converted into an NSDictionary). The values will be read-only from the outside:
#interface Checklist
-(id)initWithJSON:(NSDictionary *)json;
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
etc....
#end
With the corresponding method bodies in the .m file.
As a test, I created a class for another data element:
#interface ChecklistItem
-(id)initWithJSON:(NSDictionary *)json;
#property (readonly) NSInteger item_id;
#property (readonly) NSString *item_name;
#end
Functionally, the two classes have similar methods in the #implementation. In both cases they basically pull the appropriate value from the json and return the result. And as far as the rest of the program was concerned, the two approaches seem to be interchangeable.
So my question is:
Which approach is the best one to use?
I find either way equally readable and so far I can not find any code-reason to prefer one way over the other. I can kind of see the second option as nice since it kind-of documents the json.
You should use properties, they come in handy once you use KVO.
Also you can define public readonly properties and overwrite them in a class extension with a readwrite property that is only usable in the same class. If you try to achieve something similar you will have to deal with private helper methods — the code gets ugly.
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
This isn't standard Objective-C naming. If you want to do things properly, follow the platform conventions. Apple document this in their coding guidelines documentation.
Which approach is the best one to use?
They are equivalent as far as Objective-C is concerned. The property syntax expresses your intent at a higher level than manually creating the methods, so I would prefer that approach. It's also less code.
This is less important now that ARC will clean up memory which would have been managed
inside the setter but this is still very much best practice. The performance overhead of
calling a setter method is also negligible compared to the safety gained from always
going through the setter.
this is a subjective question and you'll get nothing but opinions back, but here is mine:
the read only properties will just write the getters for you. if you don't write a private read write propertly in your .m file or wherever and just set the ivar's directly you don't even get the will/did change value for key calls and will have to call those yourself also.
#interface ChecklistItem ()
#property (readwrite) NSInteger item_id;
#property (readwrite) NSString *item_name;
#end
To access them KVO complient inside the object you'll have to do:
self.item_id = 13;
And not:
_item_id = 13;
Of course you could just have getter methods:
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
And just wrap all changes in in your KVO methods:
[self willChangeValueForKey:#"checklist_id"];
_item_id = 13;
[self didChangeValueForKey:#"checklist_id"];
it's just a coding style choice, and sometimes leveraging what the compiler will write for you. but either option works the same.
If the values are read only, I'd think you'd want them as methods rather than as read-only properties to avoid any confusion that the values might be able to be set. Unless of course you want the subscribers to be able to use the dot notation for accessing the properties, but if you're just returning the values in the NSDictionary, the method form would be better as you're not keeping around another copy of the data.

Using #synthesize in ios Application

I was watching the wonderful Paul Haggerty in the iTunesU courses for iOS development (cause who doesn't need to refresh on the basics?) and he said something that I wasn't aware of:
"We will never access underbar ( the _ symbol) variables"
He then went on to talk about how when you use #property to declare your variables,#synthesize variable = _variable is code that's generated behind the scenes by the complier, as well as the setter and getter. Essentially that code never should appear in your app.
In all of my iOS apps I've written thus far, I always declare my variables using #property in my header file and #synthesize VARIABLE_NAME = _VARIABLE_NAME; Since watching the lecture, I'm now confused as to if I should be using #synthesize in my code at all.
Should I just use the property declaration? What difference does it make, if any, if I use the synthesize declaration in my code?
Since Mr. Haggerty doesn't use it, then why do I? (considering he's sort of an iOS demi-god). I very much feel like it's bad form to do what I've been doing.
Anyone care to clarify that issue?
Xcode 4.0 Developer Preview 4 Release Notes. Adds default automatic synthesis of properties (iOS and 64-bit OS X). You don’t need the #synthesize directive in the implementation sections for the compiler to synthesize accessors for declared properties.
So
#synthesize ivar = _ivar;
is exactly same if you omit it.
There is no longer any need for synthesize. This was also covered in a WWDC session this year. Just use properties.
Not including "#synthesize VARIABLE_NAME = _VARIABLE_NAME" will do the exact same thing as if you actually included it, since the compiler will automatically add that if you don't add anything.
with Xcode 4.5 or up. The IDE write the #synthesize statement for you.
The #synthesize statement is only write the setter and getter for you.
that, _variable_name is the instant variable.
The variable_name is only a method that returns the value of _variable_name by default.
when using the variable = <Statement or value>. its calling thesetVarable_Namemethod to set the_variable_name` by default.
Hope it helped.

List of known Xcode bugs / gotchas

Is there such a list?
I'm relatively new to iOS development and I'm think it would be great to study a list of most well-known compiler bugs or gotchas.
EDIT:
Today I spent too much time to understand what's going on with code like this:
in *.h
#interface I : NSObject {
..
NSSMutableArray* var; // typo, should be m_var;
}
#property (nonatomic, readonly) NSMutableArray* var;
in *.m
#implementation I
#synthesize var = m_var; // no warnings or anything
-(id) init
{
self = [super init];
if (self != nil)
{
// no warning or errors
m_var = [NSMutableArray new];
}
return self;
}
And I think it's time to learn some of the well-known Objective-C idiosyncrasies.
Apple’s list of bugs is internal to Apple.
I think that Open Radar is the closest thing you’ll get to a public list of bugs related to Apple products, including Xcode. It is maintained by the community — users are encouraged to post to Open Radar the bug reports that have been submitted to Apple.
The golden rule of debugging: it’s not compiler’s fault. Some behaviours are a bit strange, like the one you show here, but they are by design. As for the “bug” in question, the compiler can synthesize instance variables for you, without them having to be declared:
#interface Foo {}
#property(assign) float bar;
#end
#implementation Foo
#synthesize bar;
- (void) somewhere { bar = 1; }
#end
This is convenient and allows you to move private interfaces into the implementation file. Coming back to your example, you now have two instances variables, var and m_var, the second one acting as a storage for the var property. It’s not exactly something to be happy about, but it makes perfect sense. (Could there be a warning that you have an instance variable that doesn’t act as a store for a property with the same name?)
As this kind of behaviour is mostly by design, you won’t find it in the Radar and would have to look for a list of common Objective-C gotchas. (This is another interesting situation.)
Apple has its own bug tracker, but you can only see you own reports (!?)
Your best bet is then openradar... Which is limited.
EDIT: About your supposed Xcode Bug, even if that's not the question.
Remember that #synthesize is just syntactic sugar that will generate code at compilation.
My guess is that your var property is conflicting with your var member.
I would not say that's a bug, more a predictable issue that could be integrated in clang static analysis.
Anyway, that's obviously a code typo, a human error, tools are just there to help us, or we would write assembly bytecode directly :)

Resources