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

object_getClassName(myViewController)

返回如下内容:

_TtC5AppName22CalendarViewController

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

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


当前回答

如果你的类型是Foo,下面的代码会在Swift 3和Swift 4中给你“Foo”:

let className = String(describing: Foo.self) // Gives you "Foo"

这里大多数答案的问题是,他们给你“Foo”。当你没有该类型的任何实例时,当你真正想要的只是"Foo"时,输入"作为结果字符串。下面是“Foo”。输入“”,就像在其他答案中提到的那样。

let className = String(describing: type(of: Foo.self)) // Gives you "Foo.Type"

如果您只想要“Foo”,则不需要使用类型(of:)部分。

其他回答

这类例子用于类var.不要包含bundle的名称。

extension NSObject {
    class var className: String {
        return "\(self)"
    }
}

我建议这样的方法(非常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

有时其他解决方案会给出一个无用的名称,这取决于您试图查看的对象。在这种情况下,您可以使用以下命令获取类名作为字符串。

String(cString: object_getClassName(Any!))

⌘单击xcode中的函数,查看一些相当有用的相关方法。或者点击这里查看https://developer.apple.com/reference/objectivec/objective_c_functions

以上的解决方案对我不起作用。产生的主要问题在几个评论中提到:

MyAppName。类名称

or

MyFrameWorkName。类名称

这个解决方案适用于XCode 9, Swift 3.0:

我把它命名为classnamecinclined,这样更容易访问,也不会与未来的className()更改冲突:

extension NSObject {

static var classNameCleaned : String {

    let className = self.className()
    if className.contains(".") {
        let namesArray = className.components(separatedBy: ".")
        return namesArray.last ?? className
    } else {
        return self.className()
    }

}

}

用法:

NSViewController.classNameCleaned
MyCustomClass.classNameCleaned

你可以在Swift 4中像这样扩展NSObjectProtocol:

import Foundation

extension NSObjectProtocol {

    var className: String {
        return String(describing: Self.self)
    }
}

这将使计算变量className对所有类可用。在CalendarViewController中的print()中使用这个将在控制台中打印“CalendarViewController”。