Подтвердить что ты не робот

Проверка пути ключа времени компиляции в Swift

Когда я реализую протокол NSCoding в Objective-C, я хотел бы использовать NSStringFromSelector(@selector(name)) для получения ключевого пути свойства, например ниже

- (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;
}

Мне нравится этот путь, потому что он предотвращает опечатки без необходимости определять множество строковых констант, и я получу предупреждения, если бы переименовал эти свойства. Но я не мог найти способ сделать это в Swift, любые идеи?

4b9b3361

Ответ 1

В Swift селекторы являются строками. (Ну, там тип Selector, но прозрачно преобразуется в и из String.) Таким образом, вы можете опустить NSStringFromSelector и @selector и просто использовать строковый литерал.

Если вы хотите запечатлеть имена ваших свойств... это немного сложнее. Использование reflect() в экземпляре вашего класса возвращает объект типа Mirror. (Вставьте один из этих символов на игровой площадке и нажмите cmd-click, чтобы получить объявления в стандартном "заголовке" библиотеки.) Вы можете использовать это, чтобы пройти список классов свойств.

Это заставит ваш метод "закодировать все" выглядеть примерно так:

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)
}

Это не идеально, так как вы должны знать порядок определения свойств. Но это может быть улучшено после...