2014-09-30 2 views
25

Я успешно использую метод setValue(value, forKey: key) в своем подклассе Swift NSObject под NSKeyValueCoding.Использование setValue (значение, forKey: key) в Int? типы запускают метод кодирования, не связанный с ключом

Это прекрасно работает на опциях String, например.

var name:String? 

Однако на Int дополнительных опциях, он выходит из строя, вызывая ключевой метод неопределенного, что я переопределен для целей отладки:

override func setValue(value: AnyObject!, forUndefinedKey key: String!) { 
    println("\(self) this class is not key value coding-compliant for the key \(key)") 
} 

Так, например, клавиша myId с хорошим целочисленным значением будет вызвать метод неопределенного ключа выше.

var myId:Int? 

Если изменить приведенное выше определение, чтобы быть не опциональным, то все работает отлично:

var myId:Int = 0 

С myId как дополнительный, я попытался абсолютно все, что я могу думать в пути кастинг, развертывание, инициализация и т. д. Он просто не видит класс как ключевое значение, совместимое для этих числовых значений.

Я знаю, что это хорошее числовое значение. Изменение объявления var в String? сбои. Он также прекрасно смотрится в lldb:

Printing description of key: 
myId 
key NSObject 0x00007fb8d530ca20 0x00007fb8d530ca20 
k NSString "myId" 0x00007fa2aa942f20 
value __NSCFNumber * Int64(4348129) 0xb000000004258e13 
Printing description of value: 
4348129 
(lldb) 

Итак, вопрос, кто-нибудь использовал - в Swift - метод NSKeyValueCoding setValue(value, forKey: key)на тип Int успешно?

+1

Может быть, это потому, что Int имеет тип Any и не AnyObject. Я попытался разобрать объект на словарь и обратно и имел аналогичные проблемы. См. Https://github.com/evermeer/EVCloudKitDao/blob/master/AppMessage/AppMessage/CloudKit/EVReflection.swift. Вы можете видеть, что я попытался разобрать Any в AnyObject. Недопустимые значения по-прежнему являются проблемой, но она работает на Int. –

ответ

24

KVO не может функционировать с использованием чистых опций Swift, поскольку чистые опции Swift не являются объектами Objective-C. Swift запрещает использование dynamic или @objc с общими классами и структурами, потому что нет действительного эквивалента Objective-C, поэтому среда выполнения не настроена для поддержки KVO для экземпляров этих объектов. Что касается того, почему он работает с String?, этот тип является бесплатным по мосту до NSString, поэтому он семантически эквивалентен NSString *, объектив-C, который среда выполнения знает, как справиться. Но сравните это с Int?, семантический эквивалент которого будет Optional<Int>, а не UnsafePointer<Int> или NSNumber *, как и следовало ожидать. На данный момент вам нужно будет убедить typechecker, что в Objective-C можно безопасно представлять, используя NSNumber!.

Это полностью назад и, на мой взгляд, несчастливое ограничение системы типов. Для любых инженеров, которые сталкиваются с этим сообщением, см. Rdar: // 18624182.

+1

Я думаю, что в этой статье есть несколько технических неточностей. 1) Я изменил 'Int?' На 'NSNumber? ', И теперь он полностью соответствует KVO.2) KVO может функционировать с опциями, так как я могу использовать 'UIColor?', 'NSNumber? 'И другие типы objc. 3) Опционы специально обрабатываются генериками и даже добавляются в Objc, используя 'nonnullable',' nullable' и т. Д. – Mazyod

+0

1 подразумевается окончательным предложением первого абзаца, 2 - третьим предложением, а 3 - неправильным. Опционы привязаны к ограниченному набору типов ObjC во время выполнения, но они не являются полностью представимыми только с новыми атрибутами с возможностью NULL. Кроме того, речь идет о структурах Swift и KVO, а не объективных C-структурах. – CodaFi

3

Если вы готовы угробить Swift типы изменить:

var myId:Int? 

к:

var myId:NSNumber? 
Смежные вопросы