快速获取类名的用户可读版本(在 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&汇编快速查找分析