Lets say I have this class
:
让我们说我有这个课程:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children"
) how can I get its type? (In this case [Node]?
)
如果我有一个属性的名称(例如“children”),我该如何获得它的类型? (在这种情况下[节点]?)
I imagine having a global function like below will solve my needs:
我想像下面这样的全局函数可以解决我的需求:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
5 个解决方案
#1
8
Swift 2 (Note: Reflection changed):
Swift 2(注:反射改变了):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
自定义类:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
获取“子”属性的类型:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
物业类型检查:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
要么
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
#2
3
Reflection is achieved in Swift using the global reflect()
function. When passing an instance of some type to reflect()
it returns a MirrorType
, which has a range of properties allowing you to analyze your instance:
使用全局reflect()函数在Swift中实现反射。将某种类型的实例传递给reflect()时,它返回一个MirrorType,它具有一系列允许您分析实例的属性:
var value: Any { get } var valueType: Any.Type { get } var objectIdentifier: ObjectIdentifier? { get } var count: Int { get } var summary: String { get } var quickLookObject: QuickLookObject? { get } var disposition: MirrorDisposition { get } subscript(i: Int) -> (String, MirrorType) { get }
#3
1
This seems to work:
这似乎有效:
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
}
Here's some example code on SwiftStub.
这是SwiftStub上的一些示例代码。
Edit:
The result for optional values is only "Optional"
.
The result for arrays is only "Array"
.
The result for dictionaries is only "Dictionary"
.
可选值的结果仅为“可选”。数组的结果只是“数组”。词典的结果只是“词典”。
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
我不确定是否可以提取它是什么类型的可选/数组/字典。但我想这也是使用泛型的自定义数据结构的情况。
#4
1
Building on @PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
在@PeterKreinz的基础上回答我需要能够检查继承属性的类型,所以在上面的代码中添加了一点:
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
}
}
Hope this may help someone.
希望这可以帮助某人。
Swift 3 update:
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
}
}
#5
0
The solution provided by @peter-kreinz using Swift's class Mirror
works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
@ peter-kreinz使用Swift的类Mirror提供的解决方案可以很好地工作,当你有一个类的实例,并想知道属性的类型。但是,如果要在没有实例的情况下检查类的属性,您可能会对我的解决方案感兴趣。
I have a solution that finds the name and type of a property given any class that inherits from NSObject
.
我有一个解决方案,找到任何继承自NSObject的类的属性的名称和类型。
I wrote a lengthy explanation on * here, and my project is available here on Github,
我在这里写了一篇关于*的冗长解释,我的项目可以在Github上找到,
In short you can do something like this (but really check out the code Github):
简而言之,你可以做这样的事情(但真的检查代码Github):
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
}
#1
8
Swift 2 (Note: Reflection changed):
Swift 2(注:反射改变了):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
自定义类:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
获取“子”属性的类型:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
物业类型检查:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
要么
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
#2
3
Reflection is achieved in Swift using the global reflect()
function. When passing an instance of some type to reflect()
it returns a MirrorType
, which has a range of properties allowing you to analyze your instance:
使用全局reflect()函数在Swift中实现反射。将某种类型的实例传递给reflect()时,它返回一个MirrorType,它具有一系列允许您分析实例的属性:
var value: Any { get } var valueType: Any.Type { get } var objectIdentifier: ObjectIdentifier? { get } var count: Int { get } var summary: String { get } var quickLookObject: QuickLookObject? { get } var disposition: MirrorDisposition { get } subscript(i: Int) -> (String, MirrorType) { get }
#3
1
This seems to work:
这似乎有效:
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
}
Here's some example code on SwiftStub.
这是SwiftStub上的一些示例代码。
Edit:
The result for optional values is only "Optional"
.
The result for arrays is only "Array"
.
The result for dictionaries is only "Dictionary"
.
可选值的结果仅为“可选”。数组的结果只是“数组”。词典的结果只是“词典”。
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
我不确定是否可以提取它是什么类型的可选/数组/字典。但我想这也是使用泛型的自定义数据结构的情况。
#4
1
Building on @PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
在@PeterKreinz的基础上回答我需要能够检查继承属性的类型,所以在上面的代码中添加了一点:
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
}
}
Hope this may help someone.
希望这可以帮助某人。
Swift 3 update:
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
}
}
#5
0
The solution provided by @peter-kreinz using Swift's class Mirror
works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
@ peter-kreinz使用Swift的类Mirror提供的解决方案可以很好地工作,当你有一个类的实例,并想知道属性的类型。但是,如果要在没有实例的情况下检查类的属性,您可能会对我的解决方案感兴趣。
I have a solution that finds the name and type of a property given any class that inherits from NSObject
.
我有一个解决方案,找到任何继承自NSObject的类的属性的名称和类型。
I wrote a lengthy explanation on * here, and my project is available here on Github,
我在这里写了一篇关于*的冗长解释,我的项目可以在Github上找到,
In short you can do something like this (but really check out the code Github):
简而言之,你可以做这样的事情(但真的检查代码Github):
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
}