รับชื่อคลาสของวัตถุเป็นสตริงใน Swift


320

รับ classname ของวัตถุที่Stringใช้:

object_getClassName(myViewController)

ส่งกลับบางสิ่งเช่นนี้:

_TtC5AppName22CalendarViewController

ฉันกำลังมองหาเวอร์ชั่นที่บริสุทธิ์ : "CalendarViewController". ฉันจะล้างค่าสตริงของชื่อคลาสแทนได้อย่างไร

ฉันพบความพยายามบางคำถามเกี่ยวกับสิ่งนี้ แต่ไม่ใช่คำตอบจริง เป็นไปไม่ได้เลยเหรอ?


อีกทางหนึ่ง…ฟังก์ชัน parser ที่มีประสิทธิภาพสำหรับหน้าตานี้จะเป็นอย่างไร
Bernd

ในกรณีที่คุณต้องการตรวจสอบว่าวัตถุเป็นของคลาสที่แน่นอนดูคำตอบนี้
ความหมายมีความสำคัญ

คำตอบ:


529

สตริงจากอินสแตนซ์ :

String(describing: YourType.self)

สตริงจากประเภท :

String(describing: self)

ตัวอย่าง:

struct Foo {

    // Instance Level
    var typeName: String {
        return String(describing: Foo.self)
    }

    // Instance Level - Alternative Way
    var otherTypeName: String {
        let thisType = type(of: self)
        return String(describing: thisType)
    }

    // Type Level
    static var typeName: String {
        return String(describing: self)
    }

}

Foo().typeName       // = "Foo"
Foo().otherTypeName  // = "Foo"
Foo.typeName         // = "Foo"

ทดสอบกับclass, และstructenum


4
เป็นกรณีนี้จริงเหรอ? ตามเอกสารสำหรับสตริงสำหรับเครื่องมือเริ่มต้นนี้ "ผลลัพธ์ที่ไม่ระบุจะถูกส่งโดยอัตโนมัติโดยไลบรารีมาตรฐาน Swift" เมื่อไม่สอดคล้องกับ Streamable หรือ CustomStringConvertible หรือ CustomDebugStringConvertible ดังนั้นในขณะที่มันอาจจะแสดงค่าที่ต้องการในขณะนี้มันจะยังคงทำเช่นนั้นในอนาคต?
Tod Cunningham

3
การใช้สิ่งนี้ใน Xcode 7.3.1 & Swift 2.2 สร้างสิ่งต่อไปนี้ซึ่งไม่เหมาะ '' ให้ชื่อ = สตริงชื่อ (ตัวเอง) สตริง "<MyAppName.MyClassName: 0x ########>" ''
CodeBender

13
ใน Swift 3 คำตอบที่ถูกต้องคือโทรString(describing: MyViewController.self)ตามที่ระบุไว้ในคำตอบด้านล่าง
AmitaiB

10
แต่จะส่งคืน "MyViewController.TYPE"!
orkenstein

3
@ RudolfAdamkovičใช่แล้วนั่นจะเป็นจริง แต่ฉันไม่ชอบเขียนชื่อคลาสอย่างชัดเจน (จะทำอย่างไรถ้าฉันเปลี่ยนชื่อคลาสFooเป็นFoo2แต่สร้างคลาสFooอื่นที่นั่นอาจทำให้รหัสเบรก) ในกรณีของคลาสย่อยคุณต้องใช้อย่างใดอย่างหนึ่งtype(of:)หรือType.selfขึ้นอยู่กับสิ่งที่เหมาะกับความต้องการของคุณ อาจtype(of:)เหมาะสมกว่าสำหรับการรับชื่อคลาส
MariánČerný

182

อัปเดตเป็น SWIFT 5

เราสามารถรับรายละเอียดของชื่อประเภทได้โดยใช้ตัวแปรอินสแตนซ์ผ่านStringinitializer และสร้างวัตถุใหม่ของคลาสที่ต้องการ

print(String(describing: type(of: object)))เช่นยกตัวอย่างเช่น ที่ซึ่งobjectสามารถเป็นตัวแปรอินสแตนซ์เช่นอาร์เรย์, พจนานุกรมInt, a NSDate, ฯลฯ

เพราะNSObjectเป็นชั้นรากของที่สุดชั้นวรรณะ Objective-C, คุณอาจจะพยายามที่จะทำให้ส่วนขยายสำหรับการNSObjectที่จะได้รับชื่อชั้นของ subclass NSObjectของทุก แบบนี้:

extension NSObject {
    var theClassName: String {
        return NSStringFromClass(type(of: self))
    }
}

หรือคุณสามารถสร้าง funcion แบบคงที่ซึ่งพารามิเตอร์เป็นประเภทAny(โปรโตคอลที่ทุกประเภทสอดคล้องกันโดยปริยาย) และส่งกลับชื่อคลาสเป็นสตริง แบบนี้:

class Utility{
    class func classNameAsString(_ obj: Any) -> String {
        //prints more readable results for dictionaries, arrays, Int, etc
        return String(describing: type(of: obj))
    }
} 

ตอนนี้คุณสามารถทำสิ่งนี้:

class ClassOne : UIViewController{ /* some code here */ }
class ClassTwo : ClassOne{ /* some code here */ }

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Get the class name as String
        let dictionary: [String: CGFloat] = [:]
        let array: [Int] = []
        let int = 9
        let numFloat: CGFloat = 3.0
        let numDouble: Double = 1.0
        let classOne = ClassOne()
        let classTwo: ClassTwo? = ClassTwo()
        let now = NSDate()
        let lbl = UILabel()

        print("dictionary: [String: CGFloat] = [:] -> \(Utility.classNameAsString(dictionary))")
        print("array: [Int] = [] -> \(Utility.classNameAsString(array))")
        print("int = 9 -> \(Utility.classNameAsString(int))")
        print("numFloat: CGFloat = 3.0 -> \(Utility.classNameAsString(numFloat))")
        print("numDouble: Double = 1.0 -> \(Utility.classNameAsString(numDouble))")
        print("classOne = ClassOne() -> \((ClassOne).self)") //we use the Extension
        if classTwo != nil {
            print("classTwo: ClassTwo? = ClassTwo() -> \(Utility.classNameAsString(classTwo!))") //now we can use a Forced-Value Expression and unwrap the value
        }
        print("now = Date() -> \(Utility.classNameAsString(now))")
        print("lbl = UILabel() -> \(String(describing: type(of: lbl)))") // we use the String initializer directly

    }
}

นอกจากนี้เมื่อเราได้รับชื่อคลาสเป็น String เราสามารถสร้างอินสแตนซ์ของวัตถุใหม่ของคลาสนั้นได้ :

// Instantiate a class from a String
print("\nInstantiate a class from a String")
let aClassName = classOne.theClassName
let aClassType = NSClassFromString(aClassName) as! NSObject.Type
let instance = aClassType.init() // we create a new object
print(String(cString: class_getName(type(of: instance))))
print(instance.self is ClassOne)

บางทีนี่อาจช่วยให้ใครบางคนที่นั่น!


2
นี่ควรเป็นคำตอบที่ยอมรับได้ ขอบคุณฉันกำลังมองหาวิธีพิมพ์ชื่อคลาสโดยไม่ต้องยกตัวอย่างและพบคำตอบที่นี่ ขอบคุณพิมพ์ (String (BaseAsyncTask))
Bruno Coelho

4
classNameAsStringสามารถทำให้ง่ายclassNameขึ้นสำหรับ "ชื่อ" โดยนัยถึงประเภทของมัน theClassNameเป็น simillar to เรื่องราวของ facebook ซึ่งมีชื่อว่า thefacebook แต่เดิม
DawnSong

"diccionary" ... คอลเลกชันพจนานุกรมของ Swift เวอร์ชันอิตาลี:]
Andrew Kirna

การแก้ปัญหานี้ prepending projectname สำหรับแต่ละ classTag ProjectTest.MyViewControllerคือ ฉันจะกำจัดชื่อโครงการนี้ได้อย่างไร ฉันต้องการชื่อคลาสเท่านั้น
Sazzad Hissain Khan

132

สวิฟท์ 5

นี่คือส่วนขยายเพื่อรับtypeNameเป็นตัวแปร (ทำงานกับทั้งประเภทค่าหรือประเภทอ้างอิง)

protocol NameDescribable {
    var typeName: String { get }
    static var typeName: String { get }
}

extension NameDescribable {
    var typeName: String {
        return String(describing: type(of: self))
    }

    static var typeName: String {
        return String(describing: self)
    }
}

วิธีใช้:

// Extend with class/struct/enum...
extension NSObject: NameDescribable {}
extension Array: NameDescribable {}
extension UIBarStyle: NameDescribable { }

print(UITabBarController().typeName)
print(UINavigationController.typeName)
print([Int]().typeName)
print(UIBarStyle.typeName)

// Out put:
UITabBarController
UINavigationController
Array<Int>
UIBarStyle

12
มีความคิดใดที่ฉันจะเอา MyAppName.MyClassName ออกมาได้? ฉันสนใจ MyClassName เท่านั้น
Andrew

@Andrew คุณช่วยให้เฉพาะเจาะจงมากขึ้นในกรณีของคุณ? ฉันใช้ส่วนขยายนี้ในหลายโครงการและตอบกลับทั้งหมดตามที่ต้องการ
nahung89

1
ถ้าฉันเรียกมันจากคลาสนั้นมันจะคืน MyClassName แต่ถ้าฉันตัดมันในวิธีที่ส่งกลับสตริงชื่อคลาสและเรียกมันจากคลาสอื่นมันจะส่งคืน MyAppName.MyClassName ในขณะที่ค้นหารอบ ๆ ฉันเห็นว่าคลาสทั้งหมดมีการกำหนดเนมสเปซโดยปริยายดังนั้นหากคุณจะเรียกมันนอกคลาสของคุณคุณจะได้รับ MyAppName.MyClassName แทน MyClassName จากนั้นคุณต้องพึ่งพาการจัดการสตริงเพื่อรับชื่อคลาส
แอนดรู

1
ส่วนขยายที่มีประโยชน์มาก
Hattori Hanzō

@Andrew ไม่แน่ใจในการทำงานปัจจุบัน แต่ฉันจำได้ว่า String (อธิบาย: type (of: self)) ที่ใช้ในการส่งกลับ ModuleName.ClassName ที่จุดหนึ่ง ฉันแยกจากกัน ตัวละครและดึงวัตถุสุดท้าย
BangOperator

31

Swift 3.0

String(describing: MyViewController.self)


2
อันที่จริงtype(of: )คือ overkill ที่นั่นString(describing: MyViewController.self)จะพอเพียง
Alexander Vasenin

2
สิ่งนี้สร้างสตริงเช่น <App_Name.ClassName: 0x79e14450> สำหรับฉันซึ่งไม่เหมาะ
Doug Amos

ไม่ใช่String.init(describing: MyViewController.self)เหรอ
Iulian Onofrei

2
@IulianOnofrei คุณสามารถทำได้ แต่initไม่จำเป็น
ชิม

กำจัดคำนำหน้า AppName โดยสิ้นเชิง! ขอบคุณ
yuchen

28

ฉันขอแนะนำวิธีการดังกล่าว ( 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

พวกเขาเปลี่ยนเป็น Swift 3.0 ตอนนี้คุณสามารถรับสายจากtype(of: self)
Asad Ali

อัปเดตเป็น Swift 3
werediver

ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดในการรับชื่อประเภท: อินสแตนซ์ของคลาสใด ๆ ขึ้นอยู่กับ NSObject, enum, typealiase, ฟังก์ชั่น, คุณสมบัติ var และประเภทใด ๆ แม้แต่ค่าคงที่ สำหรับประเภทคุณต้องใช้. self ตัวอย่างเช่น typeName (Int.self), typeName (true.self) คุณไม่ต้องกังวลเกี่ยวกับชื่อโครงการเป็นส่วนหนึ่ง (เช่น AppProj [typename]) เยี่ยมมาก!
David.Chu.ca

23

หากคุณมีประเภทFooรหัสต่อไปนี้จะให้คุณเป็น"Foo"Swift 3 และ Swift 4:

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

ปัญหาส่วนใหญ่ของคำตอบที่นี่เป็นที่ที่พวกเขาให้"Foo.Type"เป็นสตริงที่เกิดขึ้นเมื่อคุณไม่ได้มีตัวอย่างของชนิดใด ๆ "Foo"เมื่อสิ่งที่คุณต้องการเป็นเพียง ต่อไปนี้จะช่วยให้คุณได้รับการ"Foo.Type"กล่าวถึงในคำตอบอื่น ๆ

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

เป็นส่วนหนึ่งที่ไม่จำเป็นถ้าคุณเพียงต้องการtype(of:)"Foo"


21

ในSwift 4.1และตอนนี้Swift 4.2 :

import Foundation

class SomeClass {
    class InnerClass {
        let foo: Int

        init(foo: Int) {
            self.foo = foo
        }
    }

    let foo: Int

    init(foo: Int) {
        self.foo = foo
    }
}

class AnotherClass : NSObject {
    let foo: Int

    init(foo: Int) {
        self.foo = foo
        super.init()
    }
}

struct SomeStruct {
    let bar: Int

    init(bar: Int) {
        self.bar = bar
    }
}

let c = SomeClass(foo: 42)
let s = SomeStruct(bar: 1337)
let i = SomeClass.InnerClass(foo: 2018)
let a = AnotherClass(foo: 1<<8)

หากคุณไม่มีตัวอย่าง:

String(describing: SomeClass.self) // Result: SomeClass
String(describing: SomeStruct.self) // Result: SomeStruct
String(describing: SomeClass.InnerClass.self) // Result: InnerClass
String(describing: AnotherClass.self) // Result: AnotherClass

หากคุณมีอินสแตนซ์โดยรอบ:

String(describing: type(of: c)) // Result: SomeClass
String(describing: type(of: s)) // Result: SomeStruct
String(describing: type(of: i)) // Result: InnerClass
String(describing: type(of: a)) // Result: AnotherClass

14

ในการรับชื่อของคลาส Swift จากวัตถุเช่นสำหรับวัตถุ var: SomeClass () ให้ใช้

String(describing: type(of: object))

ในการรับชื่อคลาส Swift จากประเภทคลาสเช่น SomeClass ให้ใช้:

String(describing: SomeClass.self)

เอาท์พุท:

"SomeClass"


13

คุณสามารถลองวิธีนี้:

self.classForCoder.description()

วิธีนี้ใช้งานได้ดีเนื่องจากมี "namespace" เต็ม (คำนำหน้าการเป็นสมาชิกเป้าหมายที่เหมาะสม) เช่นกัน
BonanzaDriver

BTW ฉันยังพบการใช้ "String (ตัวเอง)" ที่ตัวเองเป็นตัวอย่างของ MyViewController ทำงานเกินไป ... มันให้ข้อมูลเดียวกัน ... Xcode 7.1
BonanzaDriver

12

คุณสามารถใช้ฟังก์ชั่นไลบรารีมาตรฐาน Swift ที่มี_stdlib_getDemangledTypeNameลักษณะดังนี้

let name = _stdlib_getDemangledTypeName(myViewController)

@NeilJaff คุณหมายถึง "เพียงแค่สตริงตัวเลือก" หมายถึงอะไร ส่งคืนสตริงและไม่ใช่ตัวเลือก
Jernej Strasner

3
วิธีนี้จะไม่ส่งคืนชื่อของคลาสใน API ส่วนบุคคลของ FYI มันจะส่งคืนชื่อของชื่อคลาสฐานสาธารณะแรก
Tylerc230

ฉันได้รับข้อความ: การใช้ตัวระบุที่ไม่ได้แก้ไข '_stdlib_getDemangledTypeName'
Adobels

12

ในการรับชื่อประเภทเป็นสตริงในSwift 4 (ฉันไม่ได้ตรวจสอบรุ่นก่อนหน้า) เพียงแค่ใช้การแก้ไขสตริง:

"\(type(of: myViewController))"

คุณสามารถใช้.selfกับประเภทตัวเองและtype(of:_)ฟังก์ชั่นในตัวอย่าง:

// Both constants will have "UIViewController" as their value
let stringFromType = "\(UIViewController.self)"
let stringFromInstance = "\(type(of: UIViewController()))"

8

ท่านสามารถใช้กระจกเงาได้:

let vc = UIViewController()

String(Mirror(reflecting: vc).subjectType)

หมายเหตุ: วิธีนี้ยังสามารถใช้สำหรับ Structs และ Enums มี displayStyle ที่ให้สิ่งบ่งชี้ว่าเป็นโครงสร้างประเภทใด:

Mirror(reflecting: vc).displayStyle

การส่งคืนคือ enum เพื่อให้คุณสามารถ:

Mirror(reflecting: vc).displayStyle == .Class

ขอบคุณ นั่นคือสิ่งที่ได้ผลสำหรับฉัน สิ่งเดียว (อย่างน้อยใน iOS 9) คือหัวเรื่องหัวเรื่องกำลังจะสิ้นสุดใน ".Type" ดังนั้นฉันต้องลบส่วนนั้นออกจากสตริง
Nikolay Suvandzhiev

8

สวิฟท์ 5.1

คุณสามารถรับคลาส, โครงสร้าง, enum, โปรโตคอลและชื่อ NSObject Self.selfได้

print("\(Self.self)")

โปรดทราบว่านี่อาจเป็นการเติมชื่อโมดูล (แตกต่างจากString(describing: type(of: self)))
Ixx

7

Swift 3.0: คุณสามารถสร้างส่วนขยายเช่นนี้ได้มันให้ชื่อคลาสกลับคืนโดยไม่มีชื่อโครงการ

extension NSObject {
    var className: String {
        return NSStringFromClass(self as! AnyClass).components(separatedBy: ".").last ?? ""
    }

    public class var className: String {
        return NSStringFromClass(self).components(separatedBy: ".").last ?? ""
    }
}

เมื่อฉันพยายามใช้สิ่งนี้ฉันได้รับข้อผิดพลาด: ไม่สามารถส่งค่าประเภท 'ProjectName.MyViewController' (0x1020409e8) เป็น 'Swift.AnyObject.Type' (0x7fb96fc0dec0)
tylerSF

6

คุณสามารถขยายNSObjectProtocolใน Swift 4 เช่นนี้:

import Foundation

extension NSObjectProtocol {

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

สิ่งนี้จะทำให้ตัวแปรที่คำนวณได้classNameพร้อมใช้งานสำหรับคลาสทั้งหมด การใช้สิ่งนี้ภายใน a print()in CalendarViewControllerจะพิมพ์"CalendarViewController"ในคอนโซล


4

ฉันกำลังมองหาคำตอบนี้และในขณะที่ ฉันใช้ GKStateMachine และชอบสังเกตการเปลี่ยนแปลงของสถานะและต้องการวิธีง่ายๆในการดูเฉพาะชื่อคลาส ฉันไม่แน่ใจว่าเป็นเพียง iOS 10 หรือ Swift 2.3 แต่ในสภาพแวดล้อมดังกล่าวสิ่งต่อไปนี้เป็นสิ่งที่ฉันต้องการ:

let state:GKState?
print("Class Name: \(String(state.classForCoder)")

// Output:    
// Class Name: GKState


3

ในการรับชื่อคลาสเป็น String ประกาศคลาสของคุณดังต่อไปนี้

@objc(YourClassName) class YourClassName{}

และรับชื่อคลาสโดยใช้ไวยากรณ์ต่อไปนี้

NSStringFromClass(YourClassName)

3

ลองใช้reflect().summaryคลาสของตนเองหรืออินสแตนซ์ dynamicType แกะตัวเลือกก่อนที่จะรับ dynamicType มิฉะนั้น dynamicType คือ wrapper ตัวเลือก

class SampleClass { class InnerClass{} }
let sampleClassName = reflect(SampleClass.self).summary;
let instance = SampleClass();
let instanceClassName = reflect(instance.dynamicType).summary;
let innerInstance = SampleClass.InnerClass();
let InnerInstanceClassName = reflect(innerInstance.dynamicType).summary.pathExtension;
let tupleArray = [(Int,[String:Int])]();
let tupleArrayTypeName = reflect(tupleArray.dynamicType).summary;

สรุปเป็นคลาสพา ธ ที่อธิบายประเภททั่วไป ในการรับชื่อคลาสแบบง่ายจากข้อมูลสรุปให้ลองใช้วิธีนี้

func simpleClassName( complexClassName:String ) -> String {
    var result = complexClassName;
    var range = result.rangeOfString( "<" );
    if ( nil != range ) { result = result.substringToIndex( range!.startIndex ); }
    range = result.rangeOfString( "." );
    if ( nil != range ) { result = result.pathExtension; }
    return result;
}

3

การแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน ปัญหาส่วนใหญ่ที่ผลิตกล่าวถึงในหลายความคิดเห็น:

MyAppName.ClassName

หรือ

MyFrameWorkName.ClassName

โซลูชันนี้ทำงานกับ XCode 9, Swift 3.0:

ฉันตั้งชื่อclassNameCleanedเพื่อให้ง่ายต่อการเข้าถึงและไม่ขัดแย้งกับ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

2

Swift 3.0 (macOS 10.10 ขึ้นไป) คุณสามารถรับได้จาก className

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

1
เท่าที่ฉันสามารถบอกได้ว่าไม่มีคุณสมบัติ className ในตัวในคลาส Swift คุณคลาสย่อยจากบางสิ่ง
ชิม

@shim className ถูกประกาศใน Foundation แต่ดูเหมือนว่าจะมีให้เฉพาะใน macOS 10.10 และใหม่กว่า ฉันเพิ่งแก้ไขคำตอบของฉัน
Thanh VũTrần

1
หืมมันแปลก เหตุใดพวกเขาจึงไม่รวมไว้ใน iOS นอกจากนี้ยังทราบว่ามันเป็นวิธีการเช่นในNSObject developer.apple.com/reference/objectivec/nsobject/...
ชิม

2

ฉันพยายามtype(of:...)ในสนามเด็กเล่นกับ Swift 3 นี่คือผลลัพธ์ของฉัน นี่เป็นรุ่นรูปแบบรหัส

print(String(describing: type(of: UIButton.self)))
print(String(describing: type(of: UIButton())))
UIButton.Type
UIButton

เป็นการสิ้นเปลืองอินสแตนซ์ของอินสแตนซ์เพียงเพื่อกำหนดชื่อคลาส
sethfri

@sethfri ฉันใช้สิ่งนี้เพื่อกำหนดประเภทไดนามิก
Lumialxk

ฉันยังไม่เข้าใจว่าทำไมคุณต้องสร้างตัวอย่างเพื่อรับข้อมูลประเภทของคลาส
sethfri


2

ตัวอย่างชนิดนี้สำหรับคลาส var อย่ารวมชื่อของบันเดิล

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

1

หากคุณไม่ชอบชื่อ mangled คุณสามารถกำหนดชื่อของคุณเอง:

@objc(CalendarViewController) class CalendarViewController : UIViewController {
    // ...
}

อย่างไรก็ตามมันจะเป็นการดีกว่าในระยะยาวหากเรียนรู้ที่จะแยกชื่อ mangled รูปแบบมาตรฐานและมีความหมายและจะไม่เปลี่ยนแปลง


ไม่เลยสำหรับชั้นเรียนของฉันมันจะกลับมา (ExistentialMetatype) - การพึ่งพาพฤติกรรมรันไทม์ที่ไม่มีเอกสารนั้นเป็นสิ่งที่อันตรายเสมอโดยเฉพาะอย่างยิ่งสำหรับความรวดเร็วเนื่องจากมันยังอยู่ในช่วงแรก
superarts.org

1

บางครั้งโซลูชันอื่น ๆ จะให้ชื่อที่ไม่มีประโยชน์ทั้งนี้ขึ้นอยู่กับวัตถุที่คุณพยายามดู ในกรณีนั้นคุณจะได้รับชื่อคลาสเป็นสตริงโดยใช้สิ่งต่อไปนี้

String(cString: object_getClassName(Any!))

⌘คลิกฟังก์ชั่นใน xcode เพื่อดูวิธีการที่เกี่ยวข้องซึ่งมีประโยชน์พอสมควร หรือตรวจสอบที่นี่https://developer.apple.com/reference/objectivec/objective_c_functions


1

Swift 5 คุณสามารถรับ class_name เป็นสตริงด้วยString (อธิบาย: Self.self)

print(String(describing: Self.self))

0

ฉันใช้มันใน Swift 2.2

guard let currentController = UIApplication.topViewController() else { return }
currentController.classForCoder.description().componentsSeparatedByString(".").last!

0

สวิฟท์ 5.1: -

คุณยังสามารถใช้ฟังก์ชันทั่วไปเพื่อรับชื่อคลาสของวัตถุเป็นสตริงได้

struct GenericFunctions {
 static func className<T>(_ name: T) -> String {
        return "\(name)"
    }

}

เรียกใช้ฟังก์ชันนี้โดยใช้สิ่งต่อไปนี้: -

let name = GenericFunctions.className(ViewController.self)

Happy Coding :)


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.