Значение дочернего элемента из зеркального самоанализа больше не соответствует протоколу

#swift #reflection #introspection #swift-class

#swift #отражение #самоанализ #swift-класс

Вопрос:

Я пытаюсь понять возможности перегиба swift. У меня есть родительский Passport класс, дочерний элемент которого ( User ) реализует протокол Clonable , однако при самоанализе дочернего значения проверка не выполняется child.value is Clonable . Кто-нибудь может это объяснить?

 extension Clonable {
    func clone() -> Self? {
        if let me = self as? SimpleInit {
            let new = type(of: me).init()
            let mirror = Mirror(reflecting: self)
            for child in mirror.children {
                if let kp = child.label, let new = new as? NSObject {
                    if child.value is Clonable, let value = child.value as? Clonable { // this should be true
                        print("cloning (child.value) for keypath (kp)")
                        new.setValue(value.clone(), forKeyPath: kp)
                    } else {
                        print("not cloning (child.value) for keypath (kp)")
                        new.setValue(child.value, forKeyPath: kp)
                    }
                }
            }
            return new as? Self
        }
        return nil
    }
}

class Passport: NSObject, Clonable, SimpleInit, CustomReflectable {
    var customMirror: Mirror {
        return Mirror(self, children: ["user": user])
    }
    @objc var user: User?
    
    required override init() {
    }
    
    func printMe() {
        user?.printMe()
    }
}

class User: NSObject, Clonable, SimpleInit, CustomReflectable {
    var customMirror: Mirror {
        return Mirror(self, children: ["name": name])
    }
    @objc var id: Int
    @objc var name: String?
    
    required override init() {
        print("init user")
        id = Int(arc4random())
    }
    
    func printMe() {
        print("id (id) name (name)")
    }
}


let passport = Passport()
passport.user = User()
passport.user?.name = "John"
let clone = passport.clone()

passport.printMe()
clone?.printMe()
  

Это результат:

 init user // should be called second time when user gets cloned.
not cloning Optional(<__lldb_expr_92.User: 0x6000039d6420>) for keypath user
id 2046302380 name Optional("John")
id 2046302380 name Optional("John")
  

Комментарии:

1. Вы пробовали if let value = child.value as? Clonable { , этого должно быть достаточно для этого единственного теста

2. Да, я сделал, не работает 🙁