Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从属性在swift中的名称获取属性的类型/类_Swift_Reflection - Fatal编程技术网

从属性在swift中的名称获取属性的类型/类

从属性在swift中的名称获取属性的类型/类,swift,reflection,Swift,Reflection,假设我有这个类: class Node { var value: String var children: [Node]? } 如果我有它的一个属性的名称(例如“children”),如何获取它的类型?(在这种情况下,[Node]?) 我想象拥有如下的全局函数将解决我的需求: func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? { //??? } // Example

假设我有这个

class Node {
    var value: String
    var children: [Node]?
}
如果我有它的一个属性的名称(例如
“children”
),如何获取它的类型?(在这种情况下,
[Node]?

我想象拥有如下的全局函数将解决我的需求:

func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
    //???
}

// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)

使用全局
reflect()
函数在Swift中实现反射。将某个类型的实例传递到
reflect()
时,它返回一个,它具有一系列属性,允许您分析实例:

这似乎有效:

func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
    let mirror = reflect(instance)
    var variableCollection = [String: MirrorType]()

    for item in 0..<mirror.count {
        variableCollection[mirror[item].0] = mirror[item].1
    }

    if let type = variableCollection[name] {
       let longName = _stdlib_getDemangledTypeName(type.value)
       let shortName = split(longName, { $0 == "."}).last
       
       return shortName ?? longName
    }

    return nil
}
func getTypeOfVariableWithName(名称:String,实例:Any)->String?{
让镜像=反射(实例)
var variableCollection=[String:MirrorType]()
对于0..Swift 2中的项目(注意:反射已更改):

获取“子”属性的类型:

let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>


在@PeterKreinz answer的基础上,我还需要能够检查继承属性的类型,因此在上面的代码中添加了一些内容:

extension NSObject {

    // Returns the property type
    func getTypeOfProperty (name: String) -> String? {

        var type: Mirror = Mirror(reflecting: self)

        for child in type.children {
            if child.label! == name {
                return String(child.value.dynamicType)
            }
        }
        while let parent = type.superclassMirror() {
            for child in parent.children {
                if child.label! == name {
                    return String(child.value.dynamicType)
                }
            }
            type = parent
        }
        return nil
    }

}
希望这能帮助别人

Swift 3更新:

// Extends NSObject to add a function which returns property type
extension NSObject {

    // Returns the property type
    func getTypeOfProperty (_ name: String) -> String? {

        var type: Mirror = Mirror(reflecting: self)

        for child in type.children {
            if child.label! == name {
                return String(describing: type(of: child.value))
            }
        }
        while let parent = type.superclassMirror {
            for child in parent.children {
                if child.label! == name {
                    return String(describing: type(of: child.value))
                }
            }
            type = parent
        }
        return nil
    }
}

@peter kreinz使用Swift的class
Mirror
提供的解决方案在您有类的实例并想知道属性的类型时效果很好。但是,如果您想在没有类的实例的情况下检查类的属性,您可能会对我的解决方案感兴趣

我有一个解决方案,可以在继承自
NSObject
的任何类中查找属性的名称和类型

我写了一个很长的解释,我的项目是可用的

简而言之,您可以这样做(但请真正查看Github的代码):

公共类func getTypesOfProperties(包括类clazz:NSObject.Type)->字典{
变量计数=UInt32()
guard let properties=class_copyPropertyList(clazz,&count)else{return nil}
变量类型:Dictionary=[:]

对于0中的我..我以前没有听说过
reflect()
MirrorType
。谢谢你教我一些东西(投票)除了SwiftDoc.org网站外,还有其他地方记录了这些内容吗?我在Swift iBooks或标准图书馆参考中都没有看到。SwiftDoc网站是按字母顺序排列的参考,不适合学习。(你必须知道你在找什么才能使用它。)Swift中的反射似乎没有被苹果公司正式记录。正如SwiftDoc.org网站上所述,它是“Swift的自动生成文档”。这就是为什么它只按字母顺序排列。我发现它非常有用,因为你可以看到Swift本身提供的大部分内容。你是如何了解
reflect()
MirrorType
?或多或少地探索SwiftDoc.org。我有时会浏览SwiftDoc,不久前确实遇到了
MirrorType
。直到我读了一些关于Swift中反射的文章,我才明白这一点。起初我只是想把变量的名称作为字符串来获取,结果绊倒在这个StackO上问题:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
    //true -> do something
}
else
{
    //false -> do something
}
extension NSObject {

    // Returns the property type
    func getTypeOfProperty (name: String) -> String? {

        var type: Mirror = Mirror(reflecting: self)

        for child in type.children {
            if child.label! == name {
                return String(child.value.dynamicType)
            }
        }
        while let parent = type.superclassMirror() {
            for child in parent.children {
                if child.label! == name {
                    return String(child.value.dynamicType)
                }
            }
            type = parent
        }
        return nil
    }

}
// Extends NSObject to add a function which returns property type
extension NSObject {

    // Returns the property type
    func getTypeOfProperty (_ name: String) -> String? {

        var type: Mirror = Mirror(reflecting: self)

        for child in type.children {
            if child.label! == name {
                return String(describing: type(of: child.value))
            }
        }
        while let parent = type.superclassMirror {
            for child in parent.children {
                if child.label! == name {
                    return String(describing: type(of: child.value))
                }
            }
            type = parent
        }
        return nil
    }
}
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
    var count = UInt32()
    guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
    var types: Dictionary<String, Any> = [:]
    for i in 0..<Int(count) {
        guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
        let type = getTypeOf(property: property)
        types[name] = type
    }
    free(properties)
    return types
}