Programing

Swift에서 객체의 유형을 어떻게 알 수 있습니까?

lottogame 2020. 4. 10. 08:05
반응형

Swift에서 객체의 유형을 어떻게 알 수 있습니까?


프로그램이나 일부 경우를 이해하려고 할 때 실제로 어떤 유형인지 알아내는 것이 유용합니다. 디버거가 일부 유형 정보를 표시 할 수 있다는 것을 알고 있으며 일반적으로 유형 유추에 의존하여 해당 상황에서 유형을 지정하지 않는 것이 가능하지만 여전히 Python과 같은 것을 원합니다.type()

dynamicType ( 이 질문 참조 )

업데이트 : 이것은 최신 버전의 Swift에서 변경되었으며 obj.dynamicType이제 동적 유형의 인스턴스가 아닌 유형에 대한 참조를 제공합니다.

이것은 가장 유망한 것처럼 보이지만 지금까지 실제 유형을 찾을 수 없었습니다.

class MyClass {
    var count = 0
}

let mc = MyClass()

# update: this now evaluates as true
mc.dynamicType === MyClass.self

또한 새로운 객체 인스턴스화하는 클래스 참조를 사용하여 시도 하지 작업을하지만, 이상하게 나에게 내가 추가해야합니다라는 오류 준 required이니셜 라이저 :

공장:

class MyClass {
    var count = 0
    required init() {
    }
}

let myClass2 = MyClass.self
let mc2 = MyClass2()

그래도 주어진 객체의 유형을 실제로 발견하는 작은 단계 만 있습니다.

편집 : 나는 지금 관련이없는 많은 세부 사항을 제거했습니다. 관심이 있다면 편집 기록을보십시오 :)


스위프트 3 버전 :

type(of: yourObject)

스위프트 2.0 :

이런 종류의 유형 내성 검사를 수행하는 올바른 방법은 Mirror 구조체를 사용하는 것입니다 .

    let stringObject:String = "testing"
    let stringArrayObject:[String] = ["one", "two"]
    let viewObject = UIView()
    let anyObject:Any = "testing"

    let stringMirror = Mirror(reflecting: stringObject)
    let stringArrayMirror = Mirror(reflecting: stringArrayObject)
    let viewMirror = Mirror(reflecting: viewObject)
    let anyMirror = Mirror(reflecting: anyObject)

그런 다음 Mirror구조체 에서 형식 자체에 액세스하려면 다음 subjectType과 같이 속성을 사용하십시오 .

    // Prints "String"
    print(stringMirror.subjectType)

    // Prints "Array<String>"
    print(stringArrayMirror.subjectType)

    // Prints "UIView"
    print(viewMirror.subjectType)

    // Prints "String"
    print(anyMirror.subjectType)

그런 다음 다음과 같은 것을 사용할 수 있습니다.

    if anyMirror.subjectType == String.self {
        print("anyObject is a string!")
    } else {
        print("anyObject is not a string!")
    }

dynamicType.printClassName코드는 스위프트 책의 예에서입니다. 커스텀 클래스 이름을 직접 얻는 방법은 없지만 is아래 표시된 키워드를 사용하여 인스턴스 유형을 확인할 수 있습니다. 이 예제는 또한 클래스 이름을 문자열로 원하는 경우 사용자 정의 className 함수를 구현하는 방법도 보여줍니다.

class Shape {
    class func className() -> String {
        return "Shape"
    }
}

class Square: Shape {
    override class func className() -> String {
        return "Square"
    }
}

class Circle: Shape {
    override class func className() -> String {
        return "Circle"
    }
}

func getShape() -> Shape {
    return Square() // hardcoded for example
}

let newShape: Shape = getShape()
newShape is Square // true
newShape is Circle // false
newShape.dynamicType.className() // "Square"
newShape.dynamicType.className() == Square.className() // true

참고 :
하위 클래스는 NSObject이미 자체 className 함수를 구현합니다. Cocoa를 사용하는 경우이 속성을 사용할 수 있습니다.

class MyObj: NSObject {
    init() {
        super.init()
        println("My class is \(self.className)")
    }
}
MyObj()

현재 엑스 코드 6.0.1 (그들이 그것을 추가 할 때 적어도하지 않도록), 원래의 예는 이제 작동합니다 :

class MyClass {
    var count = 0
}

let mc = MyClass()
mc.dynamicType === MyClass.self // returns `true`

최신 정보:

원래 질문에 대답하기 위해 실제로 Objective-C 런타임을 일반 Swift 객체와 함께 성공적으로 사용할 수 있습니다.

다음을 시도하십시오 :

import Foundation
class MyClass { }
class SubClass: MyClass { }

let mc = MyClass()
let m2 = SubClass()

// Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground
String.fromCString(class_getName(m2.dynamicType))
String.fromCString(object_getClassName(m2))
// Returns .Some("__lldb_expr_42.MyClass")
String.fromCString(object_getClassName(mc))

변수가 X 유형인지 또는 일부 프로토콜을 준수하는지 여부를 확인 해야하는 경우 is, 또는 as?다음과 같이 사용할 수 있습니다 .

var unknownTypeVariable = …

if unknownTypeVariable is <ClassName> {
    //the variable is of type <ClassName>
} else {
    //variable is not of type <ClassName>
}

이것은 isKindOfClassObj-C 와 동일 합니다.

그리고 이것은 conformsToProtocol또는isMemberOfClass

var unknownTypeVariable = …

if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> {
    //unknownTypeVarible is of type <ClassName or ProtocolName>
} else {
    //unknownTypeVariable is not of type <ClassName or ProtocolName>
}

스위프트 3 :

if unknownType is MyClass {
   //unknownType is of class type MyClass
}

추천하는 두 가지 방법은 다음과 같습니다.

if let thisShape = aShape as? Square 

또는:

aShape.isKindOfClass(Square)

자세한 예는 다음과 같습니다.

class Shape { }
class Square: Shape { } 
class Circle: Shape { }

var aShape = Shape()
aShape = Square()

if let thisShape = aShape as? Square {
    println("Its a square")
} else {
    println("Its not a square")
}

if aShape.isKindOfClass(Square) {
    println("Its a square")
} else {
    println("Its not a square")
}

스위프트 3.0

String(describing: <Class-Name>.self)

스위프트 2.0-2.3

String(<Class-Name>)

사용 사례에 따라 다릅니다. 그러나 "가변"유형에 유용한 무언가를 원한다고 가정 해 봅시다. Swift switch문은 매우 강력하며 원하는 결과를 얻는 데 도움이 될 수 있습니다 ...

    let dd2 = ["x" : 9, "y" : "home9"]
    let dds = dd2.filter {
        let eIndex = "x"
        let eValue:Any = 9
        var r = false

        switch eValue {
        case let testString as String:
            r = $1 == testString
        case let testUInt as UInt:
            r = $1 == testUInt
        case let testInt as Int:
            r = $1 == testInt
        default:
            r = false
        }

        return r && $0 == eIndex
    }

이 경우 UInt, Int 또는 String 일 수있는 키 / 값 쌍이 포함 된 간단한 사전을 사용하십시오. .filter()사전 메소드에서 값을 올바르게 테스트하고 문자열 등의 경우에만 문자열을 테스트해야합니다. switch 문은 이것을 간단하고 안전하게 만듭니다! Any 유형의 변수에 9를 지정하면 Int 스위치가 실행됩니다. 다음과 같이 변경하십시오.

   let eValue:Any = "home9"

.. 그리고 다시 시도하십시오. 이번에는 as String사례를 실행합니다 .


"항상 참 / 실패"경고가 표시되면 사용하기 전에 Any로 전송해야 할 수 있습니다. is

(foo as Any) is SomeClass

//: Playground - noun: a place where people can play

import UIKit

class A {
    class func a() {
        print("yeah")
    }

    func getInnerValue() {
        self.dynamicType.a()
    }
}

class B: A {
    override class func a() {
        print("yeah yeah")
    }
}

B.a() // yeah yeah
A.a() // yeah
B().getInnerValue() // yeah yeah
A().getInnerValue() // yeah

참고 URL : https://stackoverflow.com/questions/24101450/how-do-you-find-out-the-type-of-an-object-in-swift

반응형