So as of xcode 7 the foundation collections are generics which is great so you can do this in ObjC:
NSSet<NSString *> *foo = [[NSSet alloc] initWithArray:@[]];
But if you try to specialize the NSSet in Swift:
let foo:NSSet<String> = NSSet(array: [])
You get this: Cannot specialize non-generic type 'NSSet'
Now, I know Swift has a Set
class as well that is generic and bridges to NSSet
, but I am doing this for NSManagedObject
subclasses so I need to support NSOrderedSet
as well and there is no ordered set in Swift yet.
My question is, is this intentional or is this an oversight? Is there any reason NSSet
wouldn't be exposed as a generic class in Swift but would be in ObjC?
An NSSet is much like an NSArray, the only difference is that the objects it holds are not ordered. So when you retrieve them they may come back in any random order, based on how easy it is for the system to retrieve them.
NSSet declares the programmatic interface for static sets of distinct objects. You establish a static set's entries when it's created, and can't modify the entries after that. NSMutableSet , on the other hand, declares a programmatic interface for dynamic sets of distinct objects.
NSSet is an unordered collection. It has no idea what the "order" of its objects are.
As the documentation says:
All
NSSet
objects can be bridged to Swift sets, so the Swift compiler replaces theNSSet
class withSet<AnyObject>
when it imports Objective-C APIs.
So, as matt already said with other words in his answer, NSSet
inside the Swift language is identical to Set<AnyObject>
, and is not the same thing as NSSet
in the current version of Objective-C language, even if they have the same name.
Continuing to cite the documentation:
You can also create an
NSSet
object directly from a Swift array literal, following the same bridging rules outlined above. When you explicitly type a constant or variable as anNSSet
object and assign it an array literal, Swift creates anNSSet
object instead of a Swift set.
In other words, it creates an object of type Set<AnyObject>
, and this is the reason of the error given by the Swift compiler (NSSet
is not generic since it correspond to the generic NSSet
in Object-C, but already instantiated on the type AnyObject
).
What you can do is to write something like:
let foo = NSSet(array: ["one", "two", "three"])
// foo has now the type NSSet<AnyObject>, which corresponds to Set<AnyObject>
let bar = foo as! Set<String>
// bar has now the type Set<String>, which has no correspondent as NSSet<...> in Swift
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With