获取对象的类名为String,使用:

object_getClassName(myViewController)

返回如下内容:

_TtC5AppName22CalendarViewController

我正在寻找纯粹的版本:“CalendarViewController”。我如何得到一个清理类名字符串代替?

我发现了一些关于这个问题的尝试,但没有一个实际的答案。难道根本不可能吗?


当前回答

如果你不喜欢这个乱七八糟的名字,你可以口述你自己的名字:

@objc(CalendarViewController) class CalendarViewController : UIViewController {
    // ...
}

然而,从长远来看,最好是学会解析这个混乱的名称。格式是标准的、有意义的,不会改变。

其他回答

来自实例的字符串:

String(describing: self)

类型中的字符串:

String(describing: YourType.self)

例子:

struct Foo {

    // Instance Level
    var typeName: String {
        return String(describing: Foo.self)
    }

    // Instance Level - Alternative Way
    var otherTypeName: String {
        let thisType = type(of: self)
        return String(describing: thisType)
    }

    // Type Level
    static var typeName: String {
        return String(describing: self)
    }

}

Foo().typeName       // = "Foo"
Foo().otherTypeName  // = "Foo"
Foo.typeName         // = "Foo"

用类、结构和enum测试。

试着反映了()。类self或实例dynamicType的摘要。在获取dynamicType之前解开可选项,否则dynamicType是可选包装器。

class SampleClass { class InnerClass{} }
let sampleClassName = reflect(SampleClass.self).summary;
let instance = SampleClass();
let instanceClassName = reflect(instance.dynamicType).summary;
let innerInstance = SampleClass.InnerClass();
let InnerInstanceClassName = reflect(innerInstance.dynamicType).summary.pathExtension;
let tupleArray = [(Int,[String:Int])]();
let tupleArrayTypeName = reflect(tupleArray.dynamicType).summary;

摘要是描述了泛型类型的类路径。要从摘要中获得简单的类名,请尝试此方法。

func simpleClassName( complexClassName:String ) -> String {
    var result = complexClassName;
    var range = result.rangeOfString( "<" );
    if ( nil != range ) { result = result.substringToIndex( range!.startIndex ); }
    range = result.rangeOfString( "." );
    if ( nil != range ) { result = result.pathExtension; }
    return result;
}

我建议这样的方法(非常Swifty):

// Swift 3
func typeName(_ some: Any) -> String {
    return (some is Any.Type) ? "\(some)" : "\(type(of: some))"
}

// Swift 2
func typeName(some: Any) -> String {
    return (some is Any.Type) ? "\(some)" : "\(some.dynamicType)"
}

它既不使用内省,也不使用手动提取(没有魔法!)


下面是一个演示:

// Swift 3

import class Foundation.NSObject

func typeName(_ some: Any) -> String {
    return (some is Any.Type) ? "\(some)" : "\(type(of: some))"
}

class GenericClass<T> {
    var x: T? = nil
}

protocol Proto1 {
    func f(x: Int) -> Int
}


@objc(ObjCClass1)
class Class1: NSObject, Proto1 {
    func f(x: Int) -> Int {
        return x
    }
}

struct Struct1 {
    var x: Int
}

enum Enum1 {
    case X
}

print(typeName(GenericClass<Int>.self)) // GenericClass<Int>
print(typeName(GenericClass<Int>()))  // GenericClass<Int>

print(typeName(Proto1.self)) // Proto1

print(typeName(Class1.self))   // Class1
print(typeName(Class1())) // Class1
print(typeName(Class1().f)) // (Int) -> Int

print(typeName(Struct1.self)) // Struct1
print(typeName(Struct1(x: 1))) // Struct1
print(typeName(Enum1.self)) // Enum1
print(typeName(Enum1.X)) // Enum1

斯威夫特5:

方式1:

print("Class: \(String(describing: self)), Function: \(#function), line: \(#line)")

输出:

Class: <Test.ViewController: 0x7ffaabc0a3d0>, Function: viewDidLoad(), line: 15

方式2:

print("Class: \(String(describing: type(of: self))), Function: \(#function), line: \(#line)")

输出:

Class: ViewController, Function: viewDidLoad(), line: 16

要在Swift 4中获得类型名为字符串(我没有检查早期版本),只需使用字符串插值:

"\(type(of: myViewController))"

你可以在类型本身上使用.self,在实例上使用type(of:_)函数:

// Both constants will have "UIViewController" as their value
let stringFromType = "\(UIViewController.self)"
let stringFromInstance = "\(type(of: UIViewController()))"