Получить пользовательскую версию имени класса в swift (в objc NSStringFromClass было хорошо)

Есть ли эквивалент NSStringFromClass в Swift, который дает читаемую пользователем версию имени класса? Я попытался использовать его с собственным классом Swift, который я создал, но, как вы можете видеть, результат, похоже, является внутренним представлением компилятора имени класса:

println(NSStringFromClass(MyClass.self))

Результат:

_TtC5test7MyClass

Я попытался добавить к классу атрибут @objc и сделать его подклассом NSObject, но это не имеет никакого значения. Я обнаружил, что если я заменил MyClass классом Objective-C с тем же именем и импортировал его в заголовок моста, он даст мне "MyClass", но это не обязательно.

Другой вариант - создать протокол для этого, который каждый класс, который я хочу использовать таким образом, должен соответствовать:

protocol Nameable {
    class var className: String { get }
}

Однако было бы проще иметь встроенный способ сделать это на языке.

Ответ 1

новый формат на основе 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!
    }
}

Ответ 2

Теперь вы можете просто сделать:

String(MyClass)

Ответ 3

На данный момент нет надежного способа сделать это. См. Комментарий разработчика Apple на https://devforums.apple.com/thread/227425

В настоящее время Swift не имеет большого значения для интроспекции.

Существует несколько механизмов интроспекции, которые используются для детские площадки. Я не знаю, предназначен ли это для API.

Некоторые Свифт методы и переменные могут быть рассмотрены с помощью Objective-C времени выполнения самоанализ. Вероятно, это лучшее решение сегодня.

В Swift есть понятие метатипа, несколько похожее на тип класса в Objective C. Его можно найти с помощью TypeName.self, например:

class Foo {
    @required  init() {
    }
}

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

Возможно, по времени выпуска метатипы будут включать в себя больше возможностей самоанализа. Я предлагаю подать запрос функции Radar для этого.

Ответ 4

В 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. Следовательно, он не имеет свойства описания, хотя шаблон "все еще делает правильные вещи".

P.S.: До b4 то же самое можно было бы выполнить с помощью отражения (obj.dynamicType).summary.

Ответ 5

Swift 3

type(of: self) выводит Имя_файла .ClassName

String(describing: type(of: self)) выводит ClassName

Ответ 6

В Swift v3.0 это сработало для меня:

String.init(describing: self.self)

Ответ 7

Если вы хотите иметь только имя класса в swift, вы можете проанализировать строку, возвращаемую NSStringFromClass().

Это делается в nameOfClass.swift из репозитория INSwift Github: https://github.com/indieSoftware/INSwift

Ответ 8

Теперь вы можете использовать следующее, чтобы получить имя класса в swift

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

Ответ 9

Это немного короче. Нет необходимости 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

myObject.description().componentsSeparatedByString(" ").first!

Это не совсем то, что вы хотите - оно добавит нежелательные ведущие '<' и завершение ':'. Но когда я отлаживаю, я ценю скорость над аккуратностью, поэтому этот быстрый + грязный трюк сработал у меня.

Ответ 13

Swift 3

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

Ответ 14

Swift 4

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