Доступ к необязательному значению PartialKeyPath в Swift 4 - PullRequest
0 голосов
/ 01 июля 2018

Используя API PartialKeyPath, как получить доступ к значению ссылки на ключевой путь? Например, это работает для необязательных значений, но не для значений Optional.

У меня проблема в том, что self[keyPath: keyPath] возвращает необязательное значение Any.

struct Element {

    let name: String
    let mass: Double?

    func stringValue(_ keyPath: PartialKeyPath<Element>) -> String {
         let value = self[keyPath: keyPath]

         switch value {
         case let string as String:
             return string.capitalized
         case nil:
             return "N/A"
         case let value:
             return String(describing: value)
         }
    }
}

let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* Optional(4.002602) */

В результате case nil никогда не выполняется, а последний случай печатается как Optional(value).

Как правильно развернуть value, чтобы извлечь необязательный файл?

1 Ответ

0 голосов
/ 02 июля 2018

Решением было использование Mirror, чтобы развернуть опционально, что кажется неоптимальным. Надеемся на лучшую поддержку Reflection в Swift!

func unwrap(_ value: Any) -> Any? {
    let mirror = Mirror(reflecting: value)

    if mirror.displayStyle != .optional {
        return value
    }

    if let child = mirror.children.first {
        return child.value
    } else {
        return nil
    }
}

struct Element {

    let name: String
    let mass: Double?

    func stringValue(_ keyPath: PartialKeyPath<AtomicElement>) -> String {
        guard let value = unwrap(self[keyPath: keyPath]) else {
            return "N/A"
        }

        switch value {
        case let string as String:
            return string.capitalized
        default:
            return String(describing: value)
        }
    }
}

let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* 4.002602 */
...