21

In Foundation, if I want to convert a set to an NSArray, I can use:

  • -[NSSet allObjects]
  • -[NSOrderedSet array]

Why are these different?

Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
user4951
  • 32,206
  • 53
  • 172
  • 282
  • 6
    cause NSSet is not ordered so allObject means that it won't be ordered, it's random, but NSOrderedSet is an alternate Array. "You can use ordered sets as an alternative to arrays when the order of elements is important and performance in testing whether an object is contained in the set is a consideration— testing for membership of an array is slower than testing for membership of a set." – Dave Nov 20 '12 at 07:41
  • @Dave I believe that's the answer. Put it up. – CodaFi Nov 20 '12 at 07:43
  • But by similar logic you could ask why then the method is named -set, not -unorderedSet or -allObjects? – Wade Tregaskis Nov 20 '12 at 07:47
  • Also, the result will be ordered, technically - it is an NSArray. It's just the order will be arbitrary. :) – Wade Tregaskis Nov 20 '12 at 07:48
  • Okay bad jokes, points taken.... I guess I'll just swallow the downvotes :( – user4951 Nov 20 '12 at 09:17

3 Answers3

21

Speculation, but:

Because when NSSet was created the only other major collection type was NSArray, which was (and still is, largely) the most common collection type. So a method called "allObjects" would obviously return an NSArray.

When NSOrderedSet was added much more recently, it had to deal with the existence of prior collections - primarily, NSArray and NSSet. So an "allObjects" method would be ambiguous. Ergo it has two methods, -array and -set.

And/or, the -array and -set methods return proxies to what are likely the same or similar classes used internally. So in a functional sense they're a little different - those proxies will see mutations made on the original NSOrderedSet. -allObjects on the other hand does not - it genuinely creates an independent array, since its internal storage is likely a hashtable or similar that isn't readily proxied.

Wade Tregaskis
  • 1,996
  • 11
  • 15
5

While there are other differences†, .allObjects does not imply a definite ordering, and .array does; and that's exactly what you are getting.


.array returns a live proxy of the underlying NSOrderedSet, and if the underlying ordered set changes, the proxy will change with it.

Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
  • Thanks! What does that mean exactly? That the returned array of the underlying NSOrderedSet are linked up with ordered set, so a change in either the array or the ordered set will be reflected in the other? A proxy is sort of like a middleman if i'm not mistaken. What implication does that have here? I tried to reorder the array, but the order was not reflected in the orderedset at least :P – Lord Fresh Aug 17 '17 at 14:19
  • 1
    `.array` return an `NSArray`, which is readonly, and you should not be able to change it directly. If you make a `mutableCopy` of that, that's a copy, detached from the original in most ways. If you want to reorder, you should do that to an underlying `NSMutableOrderedSet`. The changes will presumably show up in the array, but I've never tested this. – Clay Bridges Aug 18 '17 at 17:44
1

Also... The NSArray returned by 'allObjects' is a copy of the values in the set.

But the NSArray returned by 'array' is a proxy of the objects in the set.

Thus if you change the value of any object in the set, you will change the value of the object in the array. A copy of the ordered set is not being made. So the two properties have different names because they do different things.

OmniB
  • 51
  • 3
  • I agree kind-off, but your second paragraph should probably read something like "But the NSArray returned by 'array' is a proxy of the original set, and if the original set changes, the proxied array will change with it." – Clay Bridges Mar 03 '15 at 21:04