快速获取类名的用户可读版本(在 objc NSStringFromClass 中很好)

Posted

技术标签:

【中文标题】快速获取类名的用户可读版本(在 objc NSStringFromClass 中很好)【英文标题】:Get a user-readable version of the class name in swift (in objc NSStringFromClass was fine) 【发布时间】:2014-06-08 15:25:12 【问题描述】:

在 Swift 中是否有等效的 NSStringFromClass 提供用户可读版本的类名?我尝试将它与我创建的本机 Swift 类一起使用,但如您所见,结果似乎是编译器对类名的内部表示:

println(NSStringFromClass(MyClass.self))

结果:

_TtC5test7MyClass

我尝试将 @objc 属性添加到类中,并使其成为 NSObject 的子类,但没有任何区别。我发现如果我用同名的 Objective-C 类替换 MyClass,并将其导入桥接头中,它会给我“MyClass”,但这不是必需的。

另一种选择是为此制定一个协议,我想以这种方式使用的每个类都必须符合:

protocol Nameable 
    class var className: String  get 

但是,在语言中使用内置方法来执行此操作会更容易。

【问题讨论】:

【参考方案1】:

你现在可以这样做了:

String(MyClass)

【讨论】:

这让我莫名的高兴!谢谢娜塔莎机器人。 在 Swift 3 中这不再起作用了。 Swift 3 转换器将其更改为 String(describing: MyClass) 但这也不起作用。 @shim 你试过String(describing: self) 或者只是传递对象let object = MyClass() String(describing: object)【参考方案2】:

基于 xcode 6 beta 5 的新格式。

(项目名称)。(类名称)

func getName(classType:AnyClass) -> String 

    let classString = NSStringFromClass(classType.self)
    let range = classString.rangeOfString(".", options: NSStringCompareOptions.CaseInsensitiveSearch, range: Range<String.Index>(start:classString.startIndex, end: classString.endIndex), locale: nil)
    return classString.substringFromIndex(range!.endIndex)

最新 6.3 Xcode Swift 1.2

如果你需要一个扩展或者你可以把它放在任何常见的对象上:

public extension NSObject
    public class var nameOfClass: String
        return NSStringFromClass(self).componentsSeparatedByString(".").last!
    

    public var nameOfClass: String
        return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
    

【讨论】:

classType.self 应该写成classType 这也有效:NSStringFromClass(self).componentsSeparatedByString(".").last! 正如@NatashaTheRobot 所述。现在就使用String(MyClass)【参考方案3】:

斯威夫特 3

type(of: self) 打印 ModuleName.ClassName

String(describing: type(of: self)) 打印 ClassName

【讨论】:

【参考方案4】:

目前,没有可靠的方法来做到这一点。查看 Apple 开发者对https://devforums.apple.com/thread/227425的评论

Swift 目前没有太多的自省方式。

有一些内省机制用于 游乐场。我不知道这是否是 API。

一些斯威夫特 方法和变量可以使用 Objective-C 运行时的 内省。这可能是当今最好的解决方案。

Swift 确实有元类型的概念,有点类似于 Objective C 中的 Class 类型。您可以使用 TypeName.self 找到它,例如:

class Foo 
    @required  init() 
    


var normalFoo : Foo = Foo()
var fooType : Foo.Type = Foo.self;
var fooFromMetatype : Foo = fooType();

也许,到发布时间,元类型将包含更多的内省能力。我建议为此提交 Radar 功能请求。

【讨论】:

【参考方案5】:

在 Swift 2 beta 4 中,您可以通过类型对象获取信息:

let className = "\(String.self)"   // gives: "Swift.String"

或者如果你有一个实例:

let s = "Hello World"
let className = "\(s.dynamicType)" // gives: "Swift.String"

你得到 Module.Class 结果,比如:

Swift.String
ABC.MyGenericClass<Swift.Int>

有趣的是,返回的 Type 对象似乎不符合 CustomStringConvertible 协议。因此它没有 'description' 属性,尽管 "" 模式仍然做正确的事情。

P.S.:在 b4 之前,同样可以通过 reflect(obj.dynamicType).summary 完成。

【讨论】:

这很酷,但是直到他们在某个地方有一个明确的 className() 方法之前,我有点警惕。摘要现在可能是类名,但不能保证它会保持这种状态。【参考方案6】:

在 Swift v3.0 中,这对我有用:

String.init(describing: self.self)

【讨论】:

【参考方案7】:

----- 更新了-----

正如@ThomasW 提到的,对于 Swift 4,我们需要使用 String(describing:type(of:self))

----- 旧帖----

我更喜欢使用String(self.dynamicType)

在我的项目中使用它https://github.com/JakeLin/SwiftWeather/blob/e7165b0919dda53fd7fcba9b43fdfe150d73c6f8/SwiftWeather/ForecastView.swift#L135

【讨论】:

对于 Swift 4,这不再有效,但 String(describing:type(of:self)) 可以。 @ThomasW 谢谢,已更新帖子以反映更改。【参考方案8】:

如果你只想在 swift 中只有类的名称,你可以解析 NSStringFromClass() 返回的字符串。

这是在 INSwift Github 存储库的 nameOfClass.swift 中完成的: https://github.com/indieSoftware/INSwift

【讨论】:

请注意,这只适用于类类型——如果你尝试使用协议,Swift 会抱怨error: type 'MyProtocol' does not conform to protocol 'AnyObject'【参考方案9】:

您现在应该能够使用以下内容在 swift 中检索类名

let nameSpaceClassName = NSStringFromClass(RWTCountryPopoverViewController.self)
let className = nameSpaceClassName.componentsSeparatedByString(".").last! as String

【讨论】:

【参考方案10】:

这有点短。不需要NSStringFromClass

MyObject.self.description().componentsSeparatedByString(".").last!

【讨论】:

【参考方案11】:

这里是 Swift 3+, Xcode 8+ 示例代码:

class MySuperbClass
    let a = 4
    func getClassName() -> String? 
        return String(describing: type(of:self)).components(separatedBy: ".").first
    



let className = String(describing: type(of:MySuperbClass.self)).components(separatedBy: ".").first
//className = "MySuperbClass" 
let classNameFromObject = MySuperbClass().getClassName()
//classNameFromObject = "MySuperbClass"

【讨论】:

【参考方案12】:

斯威夫特 4

super.init(nibName:String(describing:MyClass.self), bundle: nil)

【讨论】:

【参考方案13】:
myObject.description().componentsSeparatedByString(" ").first!

这不是你想要的——它会添加一个不需要的前导'

【讨论】:

【参考方案14】:

斯威夫特 3

NSStringFromClass(self).components(separatedBy: ".").last!

【讨论】:

【参考方案15】:

在最新版本的 swift 中,以下适用于我:

NSStringFromClass(type(of: device!.self))

【讨论】:

以上是关于快速获取类名的用户可读版本(在 objc NSStringFromClass 中很好)的主要内容,如果未能解决你的问题,请参考以下文章

iOS底层探索之Runtime: objc_msgSend&汇编快速查找分析

DTracing objc_msgSend 不打印接收器类名称

iOS 获取Xcode下所有类名

iOS 获取Xcode下所有类名

iOS 获取Xcode下所有类名

iOS 获取Xcode下所有类名