49

What, if any, NSSet and NSOrderedSet operations can one perform with the new Objective-C collection literals?

For NSArray, NSDictionary, and NSNumber, see here.

FWIW, this Big Nerd Ranch Post says the indexing syntax is supposed to work for NSOrderedSet. But in my tests it does not. And I haven't been able to find anything about creating ordered sets.

Cœur
  • 37,241
  • 25
  • 195
  • 267
William Jockusch
  • 26,513
  • 49
  • 182
  • 323

2 Answers2

50

There is no Objective-C literal syntax for NSSet. It doesn't really make sense to use index subscripting to access NSSet elements, although key-based subscripting might. Either by wrapping or subclassing, you could add your own.

(Correction): Originally I had thought NSOrderedSet wasn't supported either, but it turns out that using index subscripting is supported, but there doesn't seem to be a way of initializing an NSOrderedSet with the literal syntax. However, you could use initWithArray: and pass a literal array:

NSMutableOrderedSet* oset = [[NSMutableOrderedSet alloc] initWithArray: 
    @[@"a", @"b", @"c", @"d", @42]];

oset[2] = @3;
NSLog(@"OrderedSet: %@", oset);

Outputs:

OrderedSet: {(
    a,
    b,
    3,
    d,
    42
)}

According to this excellent post by Mike Ash, you can add the methods that are used to support indexed subscripting to your own objects.

- (id)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject: (id)obj atIndexedSubscript: (NSUInteger)index;

And similar methods for object-based keying:

- (id)objectForKeyedSubscript: (id)key;
- (void)setObject: (id)obj forKeyedSubscript: (id)key;

Thus you could implement a wrapper (or with a bit more work, subclass it) around an NSSet and provide key-based retrieval. Cool!

mvl
  • 789
  • 7
  • 11
43

What about trying this, in case of NSSet:

#define $(...)  [NSSet setWithObjects:__VA_ARGS__, nil]

And using it like this:

NSSet *addresses = $(addr1,addr2,addr3,addr4);

;-)

Devarshi
  • 16,440
  • 13
  • 72
  • 125
  • 23
    I would prefer `[NSSet setWithArray:@[__VA_ARGS__]]` so that it will fail when there's a `nil` element instead of silently stopping early – user102008 Apr 19 '13 at 20:44
  • 3
    Both this answer and the comment above are awesome. Be careful if Apple ever implements the $(...) literal format though. – atreat Apr 26 '13 at 04:03
  • 6
    To safeguard against future implementation of `$(...)` literal, just use: `#define set() [NSSet setWithArray:@[__VA_ARGS__]]` – Sanjay Chaudhry May 30 '13 at 17:55
  • 1
    #define macros can be hard bugs to find since there will be no symbols generated for the expression. – jcpennypincher Aug 12 '17 at 09:20