Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <pre><code>NSMutableString *newPath = [NSMutableString stringWithCapacity:42]; </code></pre> <p>OR</p> <pre><code>NSMutableString *newPath = [[NSMutableString alloc] init]; </code></pre> <p>Is there any particular reason why I should use one or the other, on the face of it it seems easier to use the first?</p> </blockquote> <p>Yes. Always autorelease immediately unless you have a specific reason not to.</p> <p>The first reason is that it's very easy to forget to write the <code>release</code> message. If you autorelease the object in the very same statement where you create it (as in <code>[[[… alloc] init] autorelease]</code>), it's much more difficult to forget it and much more obvious when you do. The convenience factory methods (such as <code>stringWithCapacity:</code>) autorelease the object for you, so just as when you autorelease it yourself, you don't have to worry about releasing it later.</p> <p>Second, even if you do remember to write the separate <code>release</code> message, it's easy to not hit it. Two ways are early returns:</p> <pre><code>NSString *str = [[NSString alloc] initWithString:@"foo"]; BOOL success = [str writeToFile:path atomically:NO]; if (!success) return; [str release]; </code></pre> <p>and thrown or propagated exceptions:</p> <pre><code>NSString *str = [[NSString alloc] initWithString:@"foo"]; //Throws NSRangeException if str is not in the array or is only in the array as the last object NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1]; [str release]; </code></pre> <p>The “specific reason not to” is generally that you have a tight loop that creates a lot of objects, in which case you may want to manually manage as many of the objects in the loop as you can, in order to keep your object count down. However, <strong>only do this if you have evidence that this is your problem</strong> (be it hard numbers from Shark, hard numbers from Instruments, or your system going into paging hell whenever that loop runs long enough).</p> <p>Other, possibly better, solutions include splitting the loop into two nested loops (the outer one to create and drain an autorelease pool for the inner loop) and switching to NSOperation. (However, make sure you set a limit on how many operations the queue runs at a time—otherwise, <a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-09-25-gcd-practicum.html" rel="noreferrer">you may make it even easier to go into paging hell</a>.)</p> <blockquote> <p>Also is the first better as it gives the compiler a sense of size?</p> </blockquote> <p>It is better, but not for that reason.</p> <p>To the compiler, it's just another class message. The compiler does not know or care what it does; for all it knows and cares, <code>stringWithCapacity:</code> is the message to play a song to the user.</p> <p>It does give <em>NSMutableString</em> a size hint—the class will know how much character storage it may want to initially allocate. Whatever benefit you get from this is probably small (at least on the Mac), but if you have the information handy, why not use it? Conversely, I wouldn't go out of my way to compute it.</p> <blockquote> <p>I see a lot a declarations written on two lines (i.e.)</p> <pre><code>NSMutableString *newPath; newPath = [NSMutableString stringWithCapacity:42]; </code></pre> <p>Personally I prefer the one-liner, is this just another example personal style?</p> </blockquote> <p>Yes. However, there is a certain amount of risk in leaving a variable uninitialized. Definitely turn on the “Run Static Analyzer” build setting if you decide to make a habit of this.</p>
 

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