2015-08-12 1 views
4

Игра с отражениями в swift 2.0 Я пытаюсь ввести проверку дочернего значения.Отражение и типПроверка для опций

Проблема: Каждый элемент массива children в зеркале любого элемента не является необязательным, но его тип может быть необязательным ... Что происходит, конечно, у меня есть дочернее значение, даже если значение равно nil

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

Для удобства я определил индекс в расширении зеркала, которое извлекает дочерний объект с данным ярлыком

extension Mirror { 
    public subscript(key: String)->Child?{ 
     var child = children.filter { 
      var valid = false 
      if let label = $0.label { 
       valid = label == key 
      } 
      return valid 
      }.last 
     if child == nil, 
      let superMirror = superclassMirror() { 
       child = superMirror[key] 
     } 
     return child 
    } 
} 

совершенным, теперь давайте скажем у меня есть этот класс

class Rule: NSObject, AProtocol { 
    var hello: String? 
    var subRule: Rule? 
} 

Ok, теперь проблема

let aRule = Rule() 
let mirroredRule = Mirror(reflecting:aRule) 
if let child = mirroredRule["subRule"] { 
    //child.value always exists 
    //i can't do child.value is AProtocol? because child.value is not optional 
    //child.value is AProtocol of course returns false 
    //child.dynamicType is Optional(Rule) 
    if let unwrapped = unwrap(child.value) where unwrapped is AProtocol { 
     //This of course works only if child.value is not nil 
     //so the unwrap function returns an unwrapped value 
     //this is not a definitive solution 
    } 
} 

child.value не был инициализирован, поэтому он равен нулю, и я не могу ch eck его тип, используя функцию разворота. Я пишу десериализатор, поэтому мне нужно проверить var также, если он равен нулю, потому что в словаре, который будет использоваться для десериализации, он может быть определен.

private func unwrap(subject: Any) -> Any? { 
    var value: Any? 
    let mirrored = Mirror(reflecting:subject) 
    if mirrored.displayStyle != .Optional { 
     value = subject 
    } else if let firstChild = mirrored.children.first { 
     value = firstChild.value 
    } 
    return value 
} 

Надеюсь, проблема ясна. Какие-либо предложения?

+0

У меня такая же проблема, и я бы рекомендовал подать отчет об ошибке. Это определенно нарушенное поведение ИМО. – Kevin

ответ

0

Основано на this answer, я рекомендую использовать if case Optional<Any>.some(_).

Я сделал что-то недавно, чтобы убедиться, что у меня есть хотя бы один дополнительный набор в моей структуре. Вы можете вставить в игровые площадки:

struct ErrorResponse: Codable { 
    let message: String? 
    let authorizationException: [String: String]? 
    let validationException: String? 
    let generalException: String? 

    var isValid: Bool { 
     var hasAtLeastOneNonNilErrorValue = false 
     Mirror(reflecting: self).children.forEach { 
      if case Optional<Any>.some(_) = $0.value { 
       hasAtLeastOneNonNilErrorValue = true 
      } 
     } 
     return hasAtLeastOneNonNilErrorValue 
    } 
} 

let errorTest = ErrorResponse(message: "some message", authorizationException: nil, validationException: nil, generalException: nil) 
let errorTest2 = ErrorResponse(message: nil, authorizationException: nil, validationException: nil, generalException: nil) 

print("is valid: \(errorTest.isValid)") //is valid: true 
print("is valid: \(errorTest2.isValid)") //is valid: false 
Смежные вопросы