Do you have to use NSOrderedSet? Is there no "Swift" OrderedSet?
OrderedSet in Swift?
If you use NSOrderedSet in swift, you have to inherit from NSObject for uniqueness to be honored. Conforming to Hashable won't work. Also doesn't seem I can use Genrics in Swift with NSOrderedSet<Type>? Or am doing something wrong?
>> you have to inherit from NSObject for uniqueness to be honored. Conforming to Hashable won't work
Not really an accurate description of what's going on. In Cocoa's "set" behavior, uniqueness is based on the behavior of the "isEqual:" method, which is part of the NSObject protocol (and implemented in the NSObject class to default to pointer equality). If you use an @objc type as the element type, then you have to choose or implement an Obj-C class with the appropriate "isEqual:" behavior.
If you use a Swift type, it's bridged (in Swift 3) to an opaque Obj-C object wrapper. At best, I would assume, that opaque class has the default "isEqual:" behavior — pointer equality of the wrapper instance itself. This would be expected to produce unexpected uniquess results.
I don't know the official answer on the generics question, but Swift appears to take no cognizance of NSOrderedSet, so I would expect the answer to be "no". For that reason, and the one given above, I wouldn't try to use a non-NSObject subclass as the element type.
You'd probably be better off not using NSOrderedSet in Swift at all. You can get the same effect by using an array (for the order) and a set or dictionary (for expedited uniqueness checks) with about the same performance as NSOrderedSet (at least, its performance outside of its original use-case, which was Core Data). If you want to go to a bit more trouble, you could merge the two behaviors into (say) a subclass of Array.
Cool. Thanks for the info. On this, though
>>Not really an accurate description of what's going on. In Cocoa's "set" behavior, uniqueness is based on the behavior of the "isEqual:" method, which is part of the NSObject protocol (and implemented in the NSObject class to default to pointer equality). If you use an @objc type as the element type, then you have to choose or implement an Obj-C class with the appropriate "isEqual:" behavior.
Pretty sure you have to implement hash to get proper uniqueness behavior for an NSOrderedSet. For example, if you have a class:
@implementation TheGreatObject
-(instancetype)initWithStringRepresentation:(NSString*)stringRep
{
self = [super init];
if (self)
{
_stringRepresentation = stringRep;
}
return self;
}
-(BOOL)isEqual:(id)object
{
if (object == self) { return YES; }
if (object == nil) { return NO; }
if (![object isKindOfClass:[TheGreatObject class]]) { return NO; }
TheGreatObject *otherGreat = object;
return [self.stringRepresentation isEqualToString:otherGreat.stringRepresentation];
}
/*
-(NSUInteger)hash
{
return self.stringRepresentation.hash;
}*/
@endIf you do this:
TheGreatObject *one = [[TheGreatObject alloc]initWithStringRepresentation:@"One"];
TheGreatObject *two = [[TheGreatObject alloc]initWithStringRepresentation:@"One"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithObjects:one,two, nil];
NSLog(@"How many we got: %li",orderedSet.count);You'll get a set with 2 objects, if hash is commented out (like above). If you uncomment it, you'll get a set with only 1 object.
You have to implement both isEqual and hash If you implement either of them. Otherwise you break the hash table algorithm.
If you just implement equals, identical items wind up in different buckets. If you don't implement equals, identical items end up in the same bucket repeatedly.
Yeah, I thoght you had to implement both. But if you use NSOrderedSet/MutableSet from Swift, I think objects you insert in the set need to inherit from NSObject too.
Yes, of course a proper custom implementation of isEqual needs to implement hash properly too. (You should not, OTOH, necessarily assume that the hash value is used for any (putative) hash tables in the implementation. It may be used in some way, but it's transparent to clients.)
You missed my point about elements not inheriting from NSObject. Swift native types don't, but they can be automatically bridged to opaque types that do, which (as you correctly observed) breaks any reasonable attempt to control uniqueness on the Swift side.
All in all, I don't see the value of using NSOrderedSet in Swift, ever, except perhaps if you're using Core Data.
Yeah, well, sometimes I use an ordered set for something simple. It's pretty easy to check if your array contains the object...and only add items if the array does not contain the object. But if your use an ordered set you don't have to.
It's not the end of the world, but it's just one of those things that is nice to have around sometimes.
My day of Swift was fun. I'll keep using it in kiddie mode only for now though. Not because of this, but too many things seem to add up. Where dem' square brackets at