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?
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...
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