Ios 在Objective-C中的Swift类上调用NSStringFromClass将返回模块损坏的名称

Ios 在Objective-C中的Swift类上调用NSStringFromClass将返回模块损坏的名称,ios,objective-c,swift,xcode6,Ios,Objective C,Swift,Xcode6,我知道如何在Swift中获得objective-c类的可读类名 我想要实现的是从objective-c内部获取Swift类的可读类名,而不会将类名与模块弄乱 因此,如果我有一门快速课程: class Foo: NSObject{} @objc(YourClassName) class YourClassName: NSObject { } 然后在Objective-C中,我希望使用方便的NSStringFromClass将类名转换为字符串 我希望NSStringFromClass([Fo

我知道如何在Swift中获得objective-c类的可读类名

我想要实现的是从objective-c内部获取Swift类的可读类名,而不会将类名与模块弄乱

因此,如果我有一门快速课程:

class Foo: NSObject{}
@objc(YourClassName)

class YourClassName: NSObject {

}
然后在Objective-C中,我希望使用方便的NSStringFromClass将类名转换为字符串

我希望
NSStringFromClass([Foo class])
返回
@“Foo”
,但它返回
@“Bar.Foo”
,其中
Bar
是模块名

我遇到了这个问题,但它似乎有点杂乱无章,有没有更好的办法?最好不要在字符串中手动键入类名。

在SWIFT 2.1之前: 只需将
@objc(YourClassName)
放入您的swift类:

class Foo: NSObject{}
@objc(YourClassName)

class YourClassName: NSObject {

}
您可以像这样使用NSStringFromClass:

NSStringFromClass(YourClassName.self)
它也应该从Objective-C开始工作


SWIFT 2.1 在Swift 2.1中,对该答案的评论指出,这已足够:

class YourClassName: NSObject {

}
只需使用:

var str = String(YourClassName)
不过,我自己还没有从Objective-C代码中测试过这一点


有一些编辑建议希望在Swift 4中使用此选项:

var str = String(describing: YourClassName.self)
但是我还没有从Objective-C测试过这个问题。

之所以得到“Bar.Foo”,是因为swift是一种名称空间语言。我假设您在其中运行的应用程序名为Bar。因此,您可以通过以下方式获得类名:

let nameSpaceClassName = NSStringFromClass(Foo)
let className = nameSpaceClassName.componentsSeparatedByString(".").last! as String
编辑:

以上是一个非常古老的答案,应根据Swift库中最近的介绍进行更改(至少从3和4开始)。请注意,以下使用镜像接口来正确提取类的元数据:

import Foundation

/// A protocol that provides demangled information regarding core Swift structure naming components in a usable way.
public protocol StructureNameReflectable {
    /**
     An ordered list of domain named based components for the structure.
     - Example: A simple example would be:
     ```
     class Dog: NSObject {
        class Retriever: NSOjbect {}
    }
     let retriever = Retriever()
     ```
     
     `retriever.structuredName` would output `["Dog", "Retriever"]`
 */
    static var structureNameComponents: [String] { get }
    
    ///Outputs the structure's name in a string based form minus namespacing
    static var structureName: String { get }
    
    ///Outputs the structure's name in a string based form with namespacing
    static var namespacedStructureName: String { get }
    
    ///Outputs the bundle the structure is contained in
    static var bundle: Bundle { get }
}

extension StructureNameReflectable {
    
    public static var structureNameComponents: [String] {
        let type = Mirror(reflecting: self).subjectType
        let structureNameComponents = "\(type)".components(separatedBy: ".")
        return structureNameComponents
    }
    
    public static var structureName: String {
        var structureNameComponents = self.structureNameComponents
        
        if structureNameComponents.count > 1 && structureNameComponents.last == "Type" {
            structureNameComponents.removeLast()
        }

        return structureNameComponents.last!
    }
    
    public static var namespacedStructureName: String {
        return structureNameComponents.joined(separator: ".")
    }
}

extension StructureNameReflectable where Self: NSObject {
    public static var bundle: Bundle {
        return Bundle(for: self)
    }
    
    public static var className: String {
        return structureName
    }
}

extension NSObject: StructureNameReflectable { }
希望以上内容能为持续不正确使用
字符串(description:)
提供指导,请使用Swift 2.0:

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

Swift 2.1中的工作解决方案是

String(MyClass)

在objective-c中,您的最佳选择是:

NSString *yourCellName = NSStringFromClass([yourCell class]).pathExtension;

NSStringFromClass的Swift 5.1解决方案

如果需要类名的字符串描述(例如
CustomTableViewCell
),请使用:


在最新的Swift上,以下内容对我有效:

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

模块前缀名称是可读的类名。如果删除模块前缀,可能会有多个同名的类。您应该保留它。@GregParker不适用于故事板或核心数据,因此在某些情况下值得这样做:)类似于nibWithName:NSStringFromClass:-nibWithName:的建议是也使用模块前缀名作为文件名。@GregParker您有任何链接可以指向它吗?这似乎击败了模块的整体概念,因为我认为我们已经放弃了3个字母的前缀,似乎有点过分了,必须用模块名来命名所有东西。如果您更改了模块名,那么这将是一个巨大的必要重构。或者,您也可以调用nameSpaceClassName.pathExtension来获取类名,但我仍然喜欢接受的答案:)但是,
String(Foo)
更合适。@Dawnson不,不是,这将打印出描述,而该描述永远不能保证是类名或在该结构中格式化。假设时显式和非显式是有区别的如果这是硬文档化的预期行为,那么这是一件事,如果它“只适用于”特定的swift版本,这是一个不好的假设。此外,似乎您仍然继承了NSObjectFYI:当设置
@objc(YourClassName)时
对于在xib文件中设置的
UIView
的子类,我必须重新设置该类。您可能需要按照最新接受的语法@DanielGalasko更新答案,谢谢。它似乎在操场上工作得很好。您也在objective-C中尝试过吗?嗯,这与Obj-C无关。只是在Swift 2.1中,接受的语法是
String(ClassName)
over
NSStringFromClass(ClassName)
回答的问题是:“那么在Objective-C内部,我希望使用方便的NSStringFromClass将类名转换为字符串。”因此,它与Objective-C完全相关。类名不是文件,它们没有路径或扩展名。
string.init(反射:t)
是init函数原型,另请参见
string.init(t)
。我不知道为什么有人否决了这个答案,并且没有给出理由。