Compile time key path checking in Swift

i0S Swift Issue

Question or problem in the Swift programming language:

When I’m implementing NSCoding protocol in Objective-C, I’d like to use NSStringFromSelector(@selector(name)) to get the key path of a property, like below

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.accountName forKey:NSStringFromSelector(@selector(accountName))];
    [aCoder encodeObject:self.userId forKey:NSStringFromSelector(@selector(userId))];

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        _accountName = [aDecoder decodeObjectForKey:forKey:NSStringFromSelector(@selector(accountName))];
        _userId = [aDecoder decodeObjectForKey:forKey:NSStringFromSelector(@selector(userId))];
    return self;

I like this way because it prevents from mistyping without the need to define lots of string constants, and I will get warnings if I renamed those properties. But I couldn’t find a way to do this in Swift, any ideas?

How to solve the problem:

In Swift, selectors are strings. (Well, there’s the Selector type, but that transparently converts to and from String.) So you can omit NSStringFromSelector and @selector and just use a string literal.

If you’re looking to introspect the names of your properties… it’s a bit tougher. Using reflect() on an instance of your class returns an object of type Mirror. (Paste one of those symbols in your playground and cmd-click to get the declarations in the standard library “header”.) You can use that to walk the class’s list of properties.

This would make your “encode everything” method look something like this:

func encodeWithCoder(coder: NSCoder!) {
    let mirror = reflect(self)
    let (accountNameKey, _) = mirror[0]
    let (userIdKey, _) = mirror[1]

    coder.encodeObject(accountName, forKey: accountNameKey)
    coder.encodeObject(userId, forKey: userIdKey)

It’s not ideal, since you have to know the order of the properties’ definitions. But it might be improved upon…

Hope this helps!