18

Suppose I want to, for example, start creating key/value pairs using an NSMutableDictionary. I then seem to have at least three options for creating an empty, mutable dictionary with an unspecified capacity:

NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] init]; // 1
NSMutableDictionary *mutDict = [NSMutableDictionary new];          // 2
NSMutableDictionary *mutDict = [NSMutableDictionary dictionary];   // 3

Now, as I understand it, [NSObject new] is practically (if not exactly?) the same as [[NSObject alloc] init]. So we can basically merge those two options as far as I'm concerned. Regarding the [NSDictionary dictionary] method though, the documentation says:

dictionary

Creates and returns an empty dictionary.

+ (id)dictionary

Return Value

A new empty dictionary.

Discussion

This method is declared primarily for use with mutable subclasses of NSDictionary.

If you don’t want a temporary object, you can also create an empty dictionary using alloc... and init.

I have a couple of questions regarding this documentation to begin with:

Firstly, why is it even declared in NSDictionary instead of NSMutableDictionary if that is where it is intended to be used?

Secondly, what do they mean by "temporary object" in this context?

In summary: Is there a difference between the third alternative above, compared to the first two? Could it have something to do with autoreleasing objects? Does that even matter in an Automatic Reference Counting (ARC) context?

Note that this question applies to other classes as well, for example [NSData data] and [NSArray array].

I am using XCode 4.6.1 and iOS 6.1. Does it matter which one I use these days, using ARC? Perhaps from some perspective on performance?

Thank you for any clear information on this!

Community
  • 1
  • 1
Victor Zamanian
  • 3,100
  • 24
  • 31

2 Answers2

14

Firstly, why is it even declared in NSDictionary instead of NSMutableDictionary if that is where it is intended to be used?

Because it can still be useful to get an empty NSDictionary object. It's expected to be mostly used with NSMutableDictionary, but that doesn't mean it can't ever be used with NSDictionary.

Secondly, what do they mean by "temporary object" in this context?

Seems like bad documentation. They probably meant to say that if you don't want it to enter the autorelease pool then you can use alloc/init.


If you're using ARC, then whichever of these 3 methods you pick is entirely personal preference, as they'll all behave the same.

If you're not using ARC, then you should use +dictionary any time you need an autoreleased dictionary, and +alloc/init any time you need a dictionary that you're going to hold on to (e.g. by placing it in an ivar), or alternatively if you simply want to avoid autorelease and -release it manually. +new is almost never used in non-ARC code.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • Thanks! Follow-up question specifically to you: when you say "ivar" (instance variable?), that's basically the same as a @property these days, right? – Victor Zamanian May 06 '13 at 23:00
  • @VictorZamanian: `@property`s are typically backed by ivars (instance variables), although they don't have to be (you can implement your own getter/setter that works however it wants to). You can have ivars without properties, and you can have properties without ivars. But these days they often go hand-in-hand. – Lily Ballard May 06 '13 at 23:01
  • Okay, thanks. Because in my entire project I haven't been using any ivars -- only @properties -- because of the release notes of XCode 4.0: "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." Might not be super-portable, but I only use iOS in this project so should be fine as long as I declare them as `strong`? :D – Victor Zamanian May 06 '13 at 23:08
1

1) So you can use it in either place. It isn't very useful to just have a dictionary, but they put it in so you can if you ever need to. Why not?

2) I assume they mean an object which will not be retained outside of the current scope. This doesn't matter anymore in ARC days. An init'd object always had a retain count of 1, so if you alloc init (or new), the object would then need to be released. It was conventional to autorelease the result of a factory method, so you wouldn't need to worry about releasing it at the end of the scope. If you had wanted to use the result of the +dictionary method out of scope, you would have to retain it.

So in conclusion, it doesn't matter. Use whatever makes you happy.

Adam Shiemke
  • 3,734
  • 2
  • 22
  • 23