Swift:协议变量的反映

Swift:协议变量的反映,swift,mirroring,Swift,Mirroring,我有一个带有一些{get}和{get set}变量和扩展的协议,在这里我设置了前一个变量,并且在初始化类时也设置了后一个变量。我想把它们全部放在字典里,即: protocol SomeProtocol { var id: Int { get } var name: String { get set } var isItTrue: Bool { get } } extension SomeProtocol where Self: SomeClass { var i

我有一个带有一些{get}和{get set}变量和扩展的协议,在这里我设置了前一个变量,并且在初始化类时也设置了后一个变量。我想把它们全部放在字典里,即:

protocol SomeProtocol {
    var id: Int { get }
    var name: String { get set }
    var isItTrue: Bool { get }
}

extension SomeProtocol where Self: SomeClass {
    var id: Int { return 1 }
    var isItTrue: Bool { return true }

    func classProps() {
        var dict = [String: AnyObject]()
        let mirrorSelf = Mirror(reflecting: self)
        for mirrorChild in mirrorSelf.children { print(mirrorChild.label) }
    }
}

class SomeClass {
// just a class, nothing special
}

class MirrorMe: SomeClass, SomeProtocol {
    var name: String = "Some name"
}

class MirrorMirrorOnTheWall {
    func talkToTheMirror() {
        let mirrorThis = MirrorMe()
        mirrorThis.classProps() // returns only "name" property
    }
}
正如我在评论中所写,
classProps
只返回我在子类中设置的协议变量。如何在镜像的孩子中同时包含idisItTrue

p、 很抱歉这个糟糕的例子,这只是一个简单的例子:)

Mirror
来自(由我补充强调)

子结构的表示形式和可选的“显示样式” 任意主题实例

描述部分,如存储属性、集合元素、, 元组元素,或活动枚举事例——构成 具体实例。还可以提供一个“显示样式”属性 建议如何呈现此结构

属性
id
int
)和
isItTrue
bool
)可用于
MirrorMe
)的实例,但仅作为计算属性,因为
MirrorMe
不将其作为存储属性实现,而是,使用它们的默认实现作为来自
扩展SomeProtocol的计算属性,其中Self:SomeClass{…}
。因此,
MirrorMe
的计算属性
id
isItTrue
不包含在
MirrorMe
实例的子结构表示中,如使用
Mirror
的运行时内省所提供的

我们可以用一个更简单的例子来清楚地验证这一点:

class Foo {
    // a stored property
    let representedInIntrospection = 0

    // a computed property
    var notRepresented: Int { return representedInIntrospection }
}

Mirror(reflecting: Foo())
    .children
    .forEach { print($0.label, $0.value) }
        /* Optional("representedInIntrospection") 0 */
总而言之:协议中蓝印的属性,无论是否有关联的默认实现,都不能单独存储属性(蓝印属性的默认实现可能自然只包含计算属性)。这意味着,在应用此类类/结构实例的运行时自省时,只会显示在类/结构中显式声明为符合协议的存储属性的属性

最后,您从来没有提到为什么需要一个类实例存储属性的字典,但是如果将它用作生产目的,请注意。通常,类型安全语言(如Swift)中的运行时内省仅用于诊断和调试,即使它允许在运行时黑客中使用(例如,对于继承自
NSObject
的类使用KVO)。

计算属性不在
Mirror
提供的运行时内省中表示 来自(由我补充强调)

子结构的表示形式和可选的“显示样式” 任意主题实例

描述部分,如存储属性、集合元素、, 元组元素,或活动枚举事例——构成 具体实例。还可以提供一个“显示样式”属性 建议如何呈现此结构

属性
id
int
)和
isItTrue
bool
)可用于
MirrorMe
)的实例,但仅作为计算属性,因为
MirrorMe
不将其作为存储属性实现,而是,使用它们的默认实现作为来自
扩展SomeProtocol的计算属性,其中Self:SomeClass{…}
。因此,
MirrorMe
的计算属性
id
isItTrue
不包含在
MirrorMe
实例的子结构表示中,如使用
Mirror
的运行时内省所提供的

我们可以用一个更简单的例子来清楚地验证这一点:

class Foo {
    // a stored property
    let representedInIntrospection = 0

    // a computed property
    var notRepresented: Int { return representedInIntrospection }
}

Mirror(reflecting: Foo())
    .children
    .forEach { print($0.label, $0.value) }
        /* Optional("representedInIntrospection") 0 */
总而言之:协议中蓝印的属性,无论是否有关联的默认实现,都不能单独存储属性(蓝印属性的默认实现可能自然只包含计算属性)。这意味着,在应用此类类/结构实例的运行时自省时,只会显示在类/结构中显式声明为符合协议的存储属性的属性


最后,您从来没有提到为什么需要一个类实例存储属性的字典,但是如果将它用作生产目的,请注意。通常,类型安全语言(如Swift)中的运行时内省只应用于诊断和调试,即使它允许在运行时黑客中使用(例如,使用KVO从
NSObject
继承类)。

Dude,您使用的是什么版本的XCode?:)另外,我对我的问题有一些部分的回答:当我在初始化子类后中断时,我在调试器中看不到协议变量,我可以通过
po something
打印它们,但在XCodeDude的变量树中看不到它们,您使用的是什么版本的XCode?:)另外,我对我的问题有一些部分的回答:当我在初始化子类后中断时,我在调试器中看不到协议变量,我可以通过
po something
打印它们,但在XCode
var id:Int{get set}
的变量树中看不到它们是因为对代码进行了多次编辑。我纠正了它。谢谢你的回答。我原以为扩展中的赋值会产生影响,但不管怎样:)我将手动将计算属性添加到dict中。谢谢大家@用户3352185很乐意帮忙!请务必注意我答案中的最后一段(小心运行时内省黑客!)
var-id:Int{get set}
是因为对代码进行了许多编辑。我纠正了