34

approach 1:

@interface MyController : UIViewController {
    UILabel *myText;
}

@property (nonatomic, strong) UILabel *myText;

approach 2:

@interface MyController : UIViewController
@property (nonatomic, strong) UILabel *myText;

approach 3:

@interface MyController : UIViewController {
    UILabel *myText;
}

I have read some articles talking about this kind of stuff but I still do not really realize which approach I have to adopt.

I also found that someone said approach 1 is a old way so I would like to know the best practice for ios sdk 6 using ARC.

I know that declaring variables using property is a easy way for generating getter and setter and someone suggested using it. However, I would like to ask in case a variable is not for calling by another class, is it necessary for the variable using property? and set it as private variable inside the interface? Or is it better for a variable only declaring inside the interface? I would like to learn the best practice so please forgive me if this is a silly question.

Moreover, some developers write @synthesize in this way

@synthesize myText=_myText;

but some write this:

@synthesize myText;

I would also want to know the difference and which one is preferable?

Thank you very much!

fmchan
  • 760
  • 1
  • 11
  • 29
  • 1
    all your synthesize approachs and no synthesize in last XCode versions connect property to ivar named _myText, not to myText – aknew Jan 09 '13 at 14:11

2 Answers2

58

The most modern way1:

  • whenever possible, declare properties
  • don't declare iVars separately 2
  • don't @synthesize 3
  • locate as few properties as possible in you .h file 4
  • locate as many properties as possible in a class extension in your .m file 5

1 As of Xcode 4.5.2. Most of this applies back to 4.4, some of it won't compile on 4.2 (the last version available under Snow Leopard). This is preprocessor stuff, so it is all compatible back at least to iOS5 (I haven't tested on iOS4 but that should also be OK).

2 There is no point in declaring an iVar as well as a property. I am sure there are a few obscure cases where you would want to declare iVars instead of properties but I can't think of any.

3 Xcode will create an iVar with the same name as the property, preceded by an _underscore. If you (rarely) need some other kind of behaviour, you can manually @synthesize property = someOtherName. @vikingosegundo links us to this article on dynamic ivars, which is a use case for @synthesize. @RobNapier comments that you do need to @synthesize iVar = _iVar (bizarrely) if you are creating your own getters (readonly) and setters (read/write) for a property, as in this case the preprocessor will not generate the iVar for you.

4 The general rule with your interface: keep it as empty as possible. You don't actually need to declare your methods now at all, if they are for private use. If you can get the code to work without an interface declaration, that's the way to go.

5 This is an @interface block in your .m file, placed above your @implementation:

#TestClass.m

@interface TestClass()

//private property declarations here

@end

@implementation TestClass
...
foundry
  • 31,615
  • 9
  • 90
  • 125
  • don't @synthesize - its right only for some last Xcode releases, any older that 4.4 (?) will generate error at build stage. And why don't declare iVars separately (really interesting, I do not know the reason)? – aknew Jan 09 '13 at 14:05
  • 1
    -1 for "don't @synthesize." Using @synthesize on public properties is recommended for modern code and saves a lot of time writing bland getters/setters. – Eric Jan 09 '13 at 14:11
  • Yes. This is the 'most modern' way. It won't work in Xcode 4.2 (most recent Xcode for Snow Leopard). But it is compatible with iOS 5. – foundry Jan 09 '13 at 14:12
  • 22
    @Eric Please upvote me. `@synthesize` is no longer required (Xcode 4.5+), the compiler knows to generate the getters and setters without it. You don't need to generate them manually or `@synthesize`. – foundry Jan 09 '13 at 14:13
  • 2
    Right, @synthesize belongs to the dinosaurs. – Graham Perks Jan 09 '13 at 14:14
  • 1
    *And why don't declare iVars separately?* here is one (for iOS more academic reason): http://www.cocoawithlove.com/2010/03/dynamic-ivars-solving-fragile-base.html – vikingosegundo Jan 09 '13 at 14:14
  • 1
    I wasn't aware of that feature. Removed my downvote, but you should include rationale for your arguments so that your answer doesn't come off as opinion. – Eric Jan 09 '13 at 14:22
  • @Eric Thanks. I'm adding a few footnotes. – foundry Jan 09 '13 at 14:29
  • @aknew you don't declare iVars separately because the compiler now handles this detail for you. Less code leads to fewer errors. – foundry Jan 09 '13 at 14:58
  • I understand "don't declare iVars separately" as don't use ivars, always use properties, it's wrong undestanding? i.e. I often use ivar without property if i need not setter-getter or access to this data from the outside, its wrong way or not? – aknew Jan 09 '13 at 16:06
  • 3
    @aknew, yes, that is wrong. You should use a property declared in your .m file. But you should still use accessors, even internally. You should use accessor everywhere except in init and dealloc. – Rob Napier Jan 09 '13 at 16:07
  • 5
    Very good answers, but there is one case where you do need to use synthesize. If you implement custom versions of all the required accessors (getter for readonly, getter/setter for readwrite), clang will not automatically generate the ivar for you. So you need to include a "@synthesize var=_var;" to manually request it. – Rob Napier Jan 09 '13 at 16:09
  • Yes, I was going to write that same as @RobNapier. If you are overwriting both getter and setter then you need to synthesize. – Fogmeister Jan 09 '13 at 16:57
  • 1
    The answer itself here is good. However, one of the comments here asserts that you should use accessors, even for internal values. That's not good advice. Properties exist for a reason. Instance variables exist for a reason. Heck, we even have @implementation instance variables now. Use them according to their semantic meaning. Objective-C isn't a sprawling language full of concepts you don't need. It's focused. The things that are there are there for a reason. – Steven Fisher Jan 09 '13 at 17:04
  • 1
    This could be a matter of taste. I use accessors always - I find it is just clearer. There is absolutely no confusion that you are referring to an instance variable rather than something local. I also tend to take the attitude, why DIY when you can let clang do the right thing? I defer to it's greater intelligence! Obviously there are exception cases but these are not the norm and you will certainly know what you are doing when you need them. – foundry Jan 09 '13 at 17:09
  • 3
    The semantic meaning of an accessor is to access state. It is appropriately semantically internally and externally. Accessors should also be used exclusively for practical reasons, including to support KVO and subclassing. Direct access to ivars is a leading cause of pre-ARC bugs. Post-ARC it continues to be recommended in the docs and experience. "The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc." https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html – Rob Napier Jan 09 '13 at 17:12
  • @RobNapier, thanks for pointing the `@synthesize` case out, I've expanded the answer. Also yes - I don't use accessors in inits and deallocs. I didn't want to detail that in the answer though as the question was when to use properties, not when to use accessors. There seems to be much confusion floating about around these issues so I was hoping to provide a _simple_ answer. _Great_ book, btw! – foundry Jan 09 '13 at 17:15
  • Thank you so much for the answer from He Was and others who involved in discussion. It's very clear that I have to declare properties and it is really a big discovery for me that the program works fine if no @synthesize! :D – fmchan Jan 10 '13 at 01:42
  • Only a little comment, you don't need the ".m" in the class extension. It can be the same as the the interface/implementation. – Binarian Jun 19 '13 at 22:14
  • @Viktor, thanks for spotting that, I have fixed the error (my intention was no '.m') – foundry Jun 20 '13 at 00:36
  • @RobNapier What is the advantage of using accessor inside class(same .m file), I want to know – Mihir Mehta Mar 04 '15 at 11:46
  • @mihirmehta if any accessors are overridden, either in this class, any subclass, or due to KVO, then direct ivar access will bypass that, generally leading to bugs. Rules like "use an ivar unless you need an accessor" are extremely fragile and hard to audit, particularly in the face of static and dynamic subclasses. Exclusive use of accessors makes a wide variety of mistakes impossible, so should be preferred except when you explicitly need direct ivar access (and its rarity makes auditing and review easier). – Rob Napier Mar 04 '15 at 12:58
  • Thanks @RobNapier ... I have only one concern or doubt ... Wouldn't calling self.str will add overhead of calling getter method ... when i have direct access of iVar in same class ? – Mihir Mehta Mar 05 '15 at 06:33
  • The overhead is small in most cases. In a tight loop, yes, you should unload to local variables and sometimes performance-sensitive code has reason to access ivars directly. For example, pointForOffset: (https://github.com/iosptl/ios7ptl/blob/master/ch21-Text/CurvyText/CurvyText/CurvyTextView.m) is called tens of thousands of times and I used direct ivar access after profiling demonstrated that this was a major bottleneck. But because it's so rare, the `_` stands out in review as "you need to carefully consider this access." A program that is slightly faster but buggy is not a good tradeoff. – Rob Napier Mar 05 '15 at 13:29
1

You may also want to use @synthesize if you like a nice table of contents of your @synthesized properties that you can refer to and comment for clarity and organization.

Also, an @synthesize allows you to set a breakpoint on the property and trap when its value is changed.

When the compiler does everything for you, you end up being distanced from what is really happening and ignorant to it. However, not having to type out everything yourself all the time is also nice.

Alex Zavatone
  • 4,106
  • 36
  • 54