2016-09-17 3 views
3

В Swift 3 Я больше не могу проверить, является ли тип общей переменной классом (AnyObject) или нет. Следующий код возвращает true для isObject, хотя определенный тип T и переданное значение является структурным, а не классом. В Swift 2.3 и 2.2 он работает как ожидалось, и isObject - false.Как проверить, является ли общая переменная типа AnyObject

struct Foo<T> 
{ 
    var value: Any? 
    var isObject: Bool = false 

    init (val: T?) 
    { 
     if val != nil 
     { 
      // following line shows warnings in Swift 3 
      // conditional cast from 'T?' to 'AnyObject' always succeeds 
      // 'is' cast is always true 
      isObject = val is AnyObject 

      self.value = val 
     } 
    } 
} 

struct Bar 
{ 
    var bar = 0 
} 

let b = Foo<Bar>(val: Bar()) 

print(b.isObject) // -> true 

Как я могу заставить его работать правильно в Swift 3?

+0

Даже '90 - это AnyObject' возвращает' true'. Звучит как ошибка. – MirekE

+1

Связанный: [AnyObject не работает в Xcode8 beta6?] (Http://stackoverflow.com/questions/39033194/anyobject-not-working-in-xcode8-beta6) – Hamish

ответ

7

В Swift 3, все для мостового AnyObject в связи с введением _SwiftValue (см this Q&A для получения дополнительной информации), который может обернуть все, что непосредственно не мостовой на Objective-C в непрозрачном Objective-C совместимом поле.

Поэтому is AnyObject всегда будет правдой, поскольку все может быть представлено как AnyObject через упаковку в _SwiftValue.

Один из способов, чтобы проверить, является ли значение ссылочного типа (как показано на this Q&A), чтобы ввести проверить тип значения против метатипа из AnyObject, AnyClass (он же AnyObject.Type).

Для дженериков, если вы хотите, чтобы проверить статический тип T, является ли тип ссылки, вы можете сделать:

isObject = T.self is AnyClass 

Если вы хотите проверить, является ли динамический тип из значения классифицирован как T тип ссылки (например, val в вашем примере), вы можете использовать функцию type(of:) на развернутом значение, как вышеупомянутая Q & наводит на мысль:

if let val = val { 
    isObject = type(of: val) is AnyClass 

    // ... 
} 

Разница между этими двумя подходами заключается в том, что когда T имеет тип Any (или абстрактный тип абстрактного типа AnyObject), T.self is AnyClass вернет false (что может быть полезно, если вы хотите, чтобы поле могло быть ссылочным или стоимостным типом) - type(of: val) is AnyClass, однако, вернет, является ли тип val ссылочным типом.

Смежные вопросы