programing

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

abcjava 2023. 4. 26. 22:52
반응형

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

프로그램을 이해하려고 할 때 또는 일부 코너의 경우에는 어떤 유형의 프로그램인지 알아보는 것이 유용합니다.디버거가 당신에게 몇 가지 유형 정보를 보여줄 수 있다는 것을 알고 있고, 당신은 보통 그러한 상황에서 유형을 지정하지 않아도 되기 위해 유형 추론에 의존할 수 있지만, 여전히, 저는 파이썬의 것과 같은 것을 정말 갖고 싶습니다.type()

동적 유형( 질문 참조)

업데이트: 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()

그래도 주어진 물체의 유형을 실제로 발견하기 위한 작은 단계에 불과합니다.

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

Swift 3 버전:

type(of: yourObject)

Swift 2.0:

이러한 유형의 내부 검사를 수행하는 적절한 방법은 미러 구조를 사용하는 것입니다.

    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 함수를 이미 구현했습니다.코코아를 사용하는 경우 이 속성을 사용할 수 있습니다.

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

Xcode 6.0.1(최소한 언제 추가되었는지는 확실하지 않음)부터는 원래 예제가 다음과 같이 작동합니다.

class MyClass {
    var count = 0
}

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

업데이트:

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

다음을 시도합니다.

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>
}

과는▁ofent다에 해당합니다.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
}

Swift 3.0용

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

Swift 2.0 - 2.3의 경우

String(<Class-Name>)

권장되는 두 가지 방법은 다음과 같습니다.

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")
}

오래된 질문이지만 이는 내 요구사항에 적합합니다(Swift 5.x).

print(type(of: myObjectName))

댓글:저는 @JeremyLapointe가 어떻게 질문에 답하는지 모르겠습니다.사용.type(of:)실제 유형이 보다 구체적인 하위 클래스인 경우에도 컴파일 시간 정보를 확인해야 작동합니다.이제 Swift 5.1에서 유형을 동적으로 쿼리할 수 있는 더 쉬운 방법이 있습니다.dynamicType@Dash가 제안하는 것처럼.이 정보를 어디서 얻었는지에 대한 자세한 내용은 SE-0068을 참조하십시오. Swift Self를 클래스 구성원과 값 유형으로 확장합니다.


코드

스위프트 5.1

// Within an instance method context
Self.self

// Within a static method context
self

사할수있다를 할 수 .Self포함하는 유형을 가리키는 약어로(의 경우).structs,enum s, 그고리고그리.final class 타입)final classes)

설명.

제안서는 이 접근 방식이 왜 개선되는지 잘 설명합니다.dynamicType:

소하는을 Self에서는 다음과 같은 문제를 해결합니다.

  • dynamicTypeSwift의 소문자 키워드 규칙에는 예외로 남아 있습니다.이러한 변화는 Swift의 새로운 표준과 맞지 않는 특별한 사례를 제거합니다.자아는 그 의도에서 더 짧고 명확합니다.은 거울을보를 반영합니다.self현재 인스턴스를 나타냅니다.
  • 정적 멤버에 쉽게 액세스할 수 있습니다.형식 이름이 커지면 가독성이 저하됩니다. MyExtremelyLargeTypeName.staticMember타이핑하고 읽기가 불편합니다.
  • 유선 연결 형식 이름을 사용하는 코드는 형식을 자동으로 아는 코드보다 휴대성이 떨어집니다.
  • 유형의 이름을 변경하는 것은 다음을 업데이트하는 것을(를)TypeName암호의 참조사용.self.dynamicType시끄럽고 난해하다는 점에서 스위프트의 간결함과 명확함이라는 목표에 맞서 싸웁니다.

:self.dynamicType.classMember그리고.TypeName.classMember클래스 유형에서 비최종 멤버와 동의어를 사용할 수 없습니다.

" 되면 "Any"를 사용하기 에 "로해야 할 .is

(foo as Any) is SomeClass

매개 변수가 함수에 임의로 전달되면 다음과 같은 특수 유형에서 테스트할 수 있습니다.

   func isADate ( aValue : Any?) -> Bool{
        if (aValue as? Date) != nil {
            print ("a Date")
            return true
        }
        else {
            print ("This is not a date ")
            return false
        }
    }

사용 사례에 따라 다릅니다.그러나 "변수" 유형으로 유용한 작업을 수행하고 싶다고 가정해 보겠습니다. 스위트프.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()사전에서 메소드, 값을 정확하게 테스트하고 문자열일 때만 테스트해야 합니다.스위치 명령문을 사용하여 이를 간편하고 안전하게 됩니다.Any형 변수에 9를 할당하여 Int용 스위치를 실행합니다.다음으로 변경해 보십시오.

   let eValue:Any = "home9"

해 보세요...다시 시도해 보세요.에는 이는실행다니됩을 합니다.as String

//: 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

반응형