获取Swift中泛型类型的名称(字符串)

Rob*_*Rob 25 generics types introspection swift

我有一个类型为T的泛型类,我想获得实例化时传递给类的类型的名称.这是一个例子.

class MyClass<T> {
    func genericName() -> String {
        // Return the name of T.
    }
}
Run Code Online (Sandbox Code Playgroud)

我一直在寻找几个小时,我似乎无法找到任何方法来做到这一点.有人试过这个吗?

任何帮助是极大的赞赏.

谢谢

Bra*_*ton 24

您可以使用字符串插值返回任何类型的名称:

class MyClass<T> {
    func genericName() -> String {
        return "\(T.self)"
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在游乐场尝试它,它按预期工作:

var someClass = MyClass<String>()
someClass.genericName() // Returns "Swift.String"
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!你也可以写String(T.self). (3认同)

Mob*_*Dan 15

String(describing: T.self) 在Swift 3+中

var genericTypeName: String {
    return String(describing: T.self)
}
Run Code Online (Sandbox Code Playgroud)

在泛型类型,获取类型的名称T通过转换T.self或者type(of: T.self)String.我发现这type(of:)不是必要的,但值得注意,因为在其他情况下它会删除有关Type的其他细节.

以下示例演示如何在T结构和类中获取泛型类型的名称.它包含获取包含类型名称的代码.

示例包括类和结构

struct GenericStruct<T> {
    var value: T

    var genericTypeName: String {
        return String(describing: T.self)
    }

    var genericTypeDescription: String {
        return "Generic Type T: '\(genericTypeName)'"
    }

    var typeDescription: String {
        // type(of:) is necessary here to exclude the struct's properties from the string
        return "Type: '\(type(of: self))'"
    }
}

class GenericClass<T> {
    var value: T

    var genericTypeName: String {
        return String(describing: T.self)
    }

    var genericTypeDescription: String {
        return "Generic Type T: '\(genericTypeName)'"
    }

    var typeDescription: String {
        let typeName = String(describing: self)
        return "Type: '\(typeName)'"
    }

    init(value: T) {
        self.value = value
    }
}

enum TestEnum {
    case value1
    case value2
    case value3
}

let intGenericStruct: GenericStruct<Int> = GenericStruct(value: 1)
print(intGenericStruct.typeDescription)
print(intGenericStruct.genericTypeDescription)

let enumGenericStruct: GenericStruct<TestEnum> = GenericStruct(value: .value2)
print(enumGenericStruct.typeDescription)
print(enumGenericStruct.genericTypeDescription)

let intGenericClass: GenericClass<Int> = GenericClass(value: 1)
print(intGenericClass.typeDescription)
print(intGenericClass.genericTypeDescription)

let enumGenericClass: GenericClass<TestEnum> = GenericClass(value: .value2)
print(enumGenericClass.typeDescription)
print(enumGenericClass.genericTypeDescription)
Run Code Online (Sandbox Code Playgroud)

控制台输出

/*
Type: 'GenericStruct<Int>'
Generic Type T: 'Int'

Type: 'GenericStruct<TestEnum>'
Generic Type T: 'TestEnum'

Type: 'GenericClass<Swift.Int>'
Generic Type T: 'Int'

Type: 'GenericClass<TestEnum>'
Generic Type T: 'TestEnum'
*/
Run Code Online (Sandbox Code Playgroud)


Ant*_*nio 12

实现这一目标的纯粹快捷方式是不可能的.

可能的解决方法是:

class MyClass<T: AnyObject> {
    func genericName() -> String {
        let fullName: String = NSStringFromClass(T.self)
        let range = fullName.rangeOfString(".", options: .BackwardsSearch)
        if let range = range {
            return fullName.substringFromIndex(range.endIndex)
        } else {
            return fullName
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

限制依赖于它仅适用于类的事实.

如果这是泛型类型:

class TestClass {}
Run Code Online (Sandbox Code Playgroud)

NSStringFromClass() 返回全名(包括名称空间):

// Prints something like "__lldb_expr_186.TestClass" in playground
NSStringFromClass(TestClass.self)
Run Code Online (Sandbox Code Playgroud)

这就是func搜索最后一次出现的.角色的原因.

测试如下:

var x = MyClass<TestClass>()
x.genericName() // Prints "TestClass"
Run Code Online (Sandbox Code Playgroud)

更新Swift 3.0

func genericName() -> String {
    let fullName: String = NSStringFromClass(T.self)
    let range = fullName.range(of: ".")
    if let range = range {
        return fullName.substring(from: range.upperBound)
    }
    return fullName
}
Run Code Online (Sandbox Code Playgroud)