Swift에서 객체의 클래스 이름을 문자열로 가져옵니다.
다음을 사용하여 객체의 클래스 이름을 문자열로 가져 오기
object_getClassName(myViewController)
이 같은 것을 반환
_TtC5AppName22CalendarViewController
"CalendarViewController" 순수한 버전을 찾고 있습니다. 클래스 이름을 정리 한 문자열을 어떻게 얻 습니까?
나는 이것에 관한 몇 가지 시도를 발견했지만 실제 대답은 아닙니다. 불가능합니까?
인스턴스의 문자열 :
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
, struct
및 enum
.
SWIFT 5로 업데이트
이니셜 라이저를 통해 인스턴스 변수 를 사용하여 유형 이름에 대한 설명을 얻을 수 있으며 특정 클래스의 새 객체를 만들 수 있습니다String
예를 들어 print(String(describing: type(of: object)))
. 여기서 object
될 수 인스턴스 변수 어레이, 딕셔너리, 추천 Int
하는 NSDate
등
NSObject
대부분의 Objective-C 클래스 계층 구조의 루트 클래스 이므로 NSObject
의 모든 하위 클래스의 클래스 이름을 가져 오기 위해 확장을 시도 할 수 NSObject
있습니다. 이처럼 :
extension NSObject {
var theClassName: String {
return NSStringFromClass(type(of: self))
}
}
또는 매개 변수가 유형 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으로 가져 오면 해당 클래스의 새 객체를 인스 턴싱 할 수 있습니다 .
// Instanciate a class from a String
print("\nInstaciate 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)
어쩌면 이것은 누군가를 도울 수 있습니다!.
스위프트 4.2
다음은 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 {}
print(UITabBarController().typeName)
print(UINavigationController.typeName)
print([Int]().typeName)
스위프트 3.0
String(describing: MyViewController.self)
나는 그런 접근 방식을 제안합니다 ( 매우 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
type 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"
.
에서 스위프트 4.1 지금 스위프트 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
다음 _stdlib_getDemangledTypeName
과 같은 Swift 표준 라이브러리 함수를 사용할 수 있습니다 .
let name = _stdlib_getDemangledTypeName(myViewController)
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()))"
이 방법으로 시도 할 수 있습니다 :
self.classForCoder.description()
거울을 사용할 수도 있습니다.
let vc = UIViewController()
String(Mirror(reflecting: vc).subjectType)
주의 :이 방법은 Structs와 Enum에도 사용할 수 있습니다. 구조의 유형을 나타내는 displayStyle이 있습니다.
Mirror(reflecting: vc).displayStyle
반환은 열거 형이므로 다음을 수행 할 수 있습니다.
Mirror(reflecting: vc).displayStyle == .Class
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 ?? ""
}
}
객체에서 Swift 클래스의 이름을 가져 오려면 (예 : var 객체 : SomeClass ())
String(describing: type(of: object))
클래스 유형 (예 : SomeClass)에서 Swift 클래스의 이름을 가져 오려면 다음을 사용하십시오.
String(describing: SomeClass.self)
산출:
"SomeClass"
나는이 답변을 잠시 동안 찾고있었습니다. 나는 GKStateMachine을 사용하고 상태 변경을 관찰하고 클래스 이름 만 쉽게 볼 수있는 방법을 원했습니다. iOS 10 또는 Swift 2.3인지 확실하지 않지만 해당 환경에서 다음은 정확히 내가 원하는 것을 수행합니다.
let state:GKState?
print("Class Name: \(String(state.classForCoder)")
// Output:
// Class Name: GKState
다음 NSObjectProtocol
과 같이 Swift 4에서 확장 할 수 있습니다 .
import Foundation
extension NSObjectProtocol {
var className: String {
return String(describing: Self.self)
}
}
이렇게하면 계산 된 변수 className
를 모든 클래스에서 사용할 수 있습니다. print()
in 내부에서 이것을 사용하면 콘솔에서 CalendarViewController
인쇄 "CalendarViewController"
됩니다.
reflect().summary
클래스 자체 또는 인스턴스 dynamicType을 사용해보십시오 . dynamicType을 가져 오기 전에 선택 사항의 랩핑을 해제하십시오. 그렇지 않으면 dynamicType이 선택적 랩퍼입니다.
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;
}
위의 솔루션은 저에게 효과적이지 않았습니다. 대부분의 문제는 여러 의견에서 언급되었습니다.
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
클래스 이름을 문자열로 얻으려면 다음과 같이 클래스를 선언하십시오.
@objc(YourClassName) class YourClassName{}
다음 구문을 사용하여 클래스 이름을 얻습니다.
NSStringFromClass(YourClassName)
Swift 3.0 (macOS 10.10 이상), className에서 얻을 수 있습니다
self.className.components(separatedBy: ".").last!
type(of:...)
Swift 3으로 놀이터에서 시도 했습니다. 이것이 나의 결과입니다. 이것은 코드 형식 버전입니다.
print(String(describing: type(of: UIButton.self)))
print(String(describing: type(of: UIButton())))
UIButton.Type
UIButton
클래스의 이름을 다음과 같이 할 수 있습니다.
class Person {}
String(describing: Person.self)
맹 글링 된 이름이 마음에 들지 않으면 자신의 이름을 지정할 수 있습니다.
@objc(CalendarViewController) class CalendarViewController : UIViewController {
// ...
}
그러나 장기적으로 맹 글링 된 이름을 구문 분석하는 방법을 배우는 것이 좋습니다. 형식은 표준적이고 의미가 있으며 변경되지 않습니다.
Swift 2.2에서 사용합니다
guard let currentController = UIApplication.topViewController() else { return }
currentController.classForCoder.description().componentsSeparatedByString(".").last!
때로는 다른 솔루션에서 보려는 객체에 따라 유용한 이름이 아닌 경우가 있습니다. 이 경우 다음을 사용하여 클래스 이름을 문자열로 얻을 수 있습니다.
String(cString: object_getClassName(Any!))
⌘ xcode에서 함수를 클릭하면 매우 유용한 관련 방법을 볼 수 있습니다. 또는 여기에서 확인하십시오 https://developer.apple.com/reference/objectivec/objective_c_functions
스위프트 5
NSStringFromClass(CustomClass.self)
필자의 경우 String (describing : self)는 다음과 같은 것을 반환했습니다.
<My_project.ExampleViewController : 0x10b2bb2b0>
하지만 getSimpleName
Android 와 같은 것을 갖고 싶습니다 .
그래서 약간의 확장을 만들었습니다.
extension UIViewController {
func getSimpleClassName() -> String {
let describing = String(describing: self)
if let dotIndex = describing.index(of: "."), let commaIndex = describing.index(of: ":") {
let afterDotIndex = describing.index(after: dotIndex)
if(afterDotIndex < commaIndex) {
return String(describing[afterDotIndex ..< commaIndex])
}
}
return describing
}
}
이제는 다음을 반환합니다.
ExampleViewController
UIViewController 대신 NSObject를 확장해도 작동합니다. 위의 기능은 또한 안전합니다 :)
참고 URL : https://stackoverflow.com/questions/24494784/get-class-name-of-object-as-string-in-swift
'Programing' 카테고리의 다른 글
하나의 SQL 문에서 모든 테이블, 저장 프로 시저, 트리거, 제약 조건 및 모든 종속성을 삭제하십시오. (0) | 2020.03.23 |
---|---|
경고 대화 상자를 화면 크기의 90 %로 채우는 방법은 무엇입니까? (0) | 2020.03.23 |
Vim 내부에서 터미널을 어떻게 실행합니까? (0) | 2020.03.23 |
if-else 속기를 사용할 때 두 번째 표현식 생략 (0) | 2020.03.23 |
동사없이 REST URL을 작성하는 방법은 무엇입니까? (0) | 2020.03.23 |