Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>A leading underscore is a naming convention helpful to differentiate between instance variables and accessors. For the compiler it is just a common ivar rename.</p> <p>Consider the difference (non ARC code):</p> <pre><code>self.date = [NSDate date]; // OK, the setter releases the old value first date = [NSDate date]; // WRONG, skipping the setter causes a memory leak _date = [NSDate date]; // WRONG but easier to see it's not a local variable </code></pre> <p>With ARC variables won't be leaked, but it is still wrong to skip the @property attributes:</p> <pre><code>@property (copy) string; // ... self.string = someString; // OK, string is copied string = someString; // WRONG string is retained but not copied _string = someString; // WRONG but hopefully easier to see </code></pre> <p>Even worst, some APIs like Core Data rely on KVC notifications to perform lazy loading. If you accidentally skip the accessors, your data will come back as nil.</p> <p>This is the reason you often find <code>@synthesize var=_var</code>, which makes </p> <ul> <li><code>self.var</code> an accessor reference (invoking setters and getters), </li> <li><code>_var</code> a direct access reference (skipping setters and getters), </li> <li>and <code>var</code> an invalid reference. </li> </ul> <p>Given that <code>@synthesize var=_var</code> is autogenerated by LLVM 4.0 when <code>@synthesize</code> is omitted, you can consider this the default naming convention in Objective-C.</p> <p>Keep reading for details...</p> <hr> <h2>Modern runtime</h2> <p>In Objective-C 2.0 you declare variables like this:</p> <pre><code>@interface User : NSObject @property (nonatomic, assign) NSInteger age; @end @implementation User { @synthesize age; // this line can be omitted since LLVM 4.0 @end </code></pre> <p>which is translated by the compiler as follows:</p> <pre><code>@interface User : NSObject { NSInteger age; } @end @implementation User -(void)setAge:(NSInteger)newAge { age=newAge; } -(void)age { return age; } @end </code></pre> <p>If you prefer to use the underscore convention just add the following:</p> <pre><code>@synthesize age=_age; </code></pre> <p>That's all you need because <em><a href="http://developer.apple.com/library/mac/documentation/cocoa/conceptual/objectivec/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW3" rel="nofollow noreferrer">with the modern runtime</a>, if you do not provide an instance variable, the compiler adds one for you</em>. Here is the code that gets compiled:</p> <pre><code>@interface User : NSObject { NSInteger _age; } @end @implementation User -(void)setAge:(NSInteger)newAge { _age=newAge; } -(void)age { return _age; } @end </code></pre> <p>What happens if you add both the ivar and the @property? If the variable has the same name and type, the compiler uses it instead generating a new variable. Quoting The Objective-C Programming Language > Declared Properties > <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW9" rel="nofollow noreferrer">Property Implementation Directives</a>:</p> <blockquote> <p>There are differences in the behavior of accessor synthesis that depend on the runtime:</p> <ul> <li><p>For the modern runtimes, instance variables are synthesized as needed. <em>If an instance variable of the same name already exists, it is used.</em></p></li> <li><p>For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. <em>If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used</em> —otherwise, you get a compiler error.</p></li> </ul> </blockquote> <h2>Legacy runtime</h2> <p>But if you need to <a href="http://developer.apple.com/library/mac/documentation/cocoa/conceptual/objectivec/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW3" rel="nofollow noreferrer">support the legacy runtime</a> <em>you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the @synthesize statement</em>. </p> <p>So the legacy code without underscores would be:</p> <pre><code>@interface User : NSObject { NSInteger age; } @property (nonatomic, assign) NSInteger age; @end @implementation User @synthesize age; @end </code></pre> <p>Or if you prefer the underscore convention:</p> <pre><code>@interface User : NSObject { NSInteger _age; } @property (nonatomic, assign) NSInteger age; @end @implementation User @synthesize age = _age; @end </code></pre> <h2>What is the best way?</h2> <p>Apple discourages the use of underscore in methods, but not on variables!.</p> <p>Apple on methods: <em><a href="http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002931-BBCFHEAB" rel="nofollow noreferrer">Coding Guidelines for Cocoa: Typographic Conventions</a></em>:</p> <blockquote> <p><strong>Avoid the use of the underscore character as a prefix meaning private, especially in methods.</strong> Apple reserves the use of this convention. Use by third parties could result in name-space collisions; they might unwittingly override an existing private method with one of their own, with disastrous consequences.</p> </blockquote> <p>Apple on variables: <a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757" rel="nofollow noreferrer">Declared Properties and Instance Variables</a></p> <blockquote> <p>Make sure the name of the instance variable concisely describes the attribute stored. Usually, you should not access instance variables directly, instead you should use accessor methods (you do access instance variables directly in init and dealloc methods). <strong>To help to signal this, prefix instance variable names with an underscore (_)</strong>, for example: <code>@implementation MyClass { BOOL _showsTitle; }</code></p> </blockquote> <p><em><a href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf" rel="nofollow noreferrer">ISO/IEC 9899 7.1.3 Reserved identifiers</a></em> (aka C99):</p> <blockquote> <ul> <li>All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use. </li> <li>All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.</li> </ul> </blockquote> <p>On top of that, double leading underscore is traditionally reserved for the vendor of the preprocessor / compiler / library. This avoids the case where you use <code>__block</code> somewhere in your code, and Apple introduces that as a new non-standard keyword.</p> <p><em><a href="http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml" rel="nofollow noreferrer">Google Objective-C Style guide</a></em>:</p> <blockquote> <p>Variable Names Variables names start with a lowercase and use mixed case to delimit words. Class member variables have <strong>trailing</strong> underscores. For example: myLocalVariable, myInstanceVariable_. Members used for KVO/KVC bindings may begin with a leading underscore iff use of Objective-C 2.0's @property isn't allowed.</p> </blockquote> <p>Google's trailing underscore doesn't force you to type one more character before Xcode fires the autocomplete, but you'll realize it is an instance variable slower if the underscore is a suffix.</p> <p>Leading underscore is also discouraged in C++ (see <a href="https://stackoverflow.com/questions/228783/">What are the rules about using an underscore in a C++ identifier?</a>) and Core Data properties (try adding a leading underscore in the model and you'll get "Name must begin with a letter").</p> <p>Whatever you chose, collisions are unlikely to happen, and if they do, you'll get a warning from the compiler. When in doubt, use the default LLVM way: <code>@synthesize var=_var;</code></p> <hr> <p>I own an edit of this post to reading <a href="https://www.bignerdranch.com/blog/a-motivation-for-ivar-decorations/" rel="nofollow noreferrer">A Motivation for ivar decorations</a> by Mark Dalrymple. You may want to check it out.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload