आप किसी वस्तु के प्रकार (स्विफ्ट में) का पता कैसे लगा सकते हैं?


255

जब एक कार्यक्रम, या कुछ कोने-मामलों को समझने की कोशिश कर रहा है, तो यह वास्तव में यह पता लगाने में सक्षम होना चाहिए कि कुछ प्रकार क्या है। मुझे पता है कि डिबगर आपको कुछ प्रकार की जानकारी दिखा सकता है, और आप आमतौर पर उन स्थितियों में प्रकार को निर्दिष्ट नहीं करने के साथ दूर होने के लिए टाइप इनेंस पर भरोसा कर सकते हैं, लेकिन फिर भी, मैं वास्तव में अजगर की तरह कुछ करना चाहूंगाtype()

डायनामिक टाइप ( यह प्रश्न देखें )

अद्यतन: यह स्विफ्ट के हाल के संस्करण में बदल दिया गया है, 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()

हालांकि वास्तव में किसी भी दी गई वस्तु के प्रकार की खोज की दिशा में केवल एक छोटा कदम है

संपादित करें : मैंने अब अप्रासंगिक विवरणों की एक बड़ी संख्या को हटा दिया है - यदि आप रुचि रखते हैं, तो संपादन इतिहास को देखें :)



1
दिलचस्प है, print(mc)या dump(mc)एक सारांश मुद्रित करेगा (जिसे आप प्राप्त कर सकते हैं toString(mc)या reflect(mc).summary), जिसमें कहीं पर वर्ग का नाम होगा। लेकिन यह स्पष्ट नहीं है कि केवल अपने आप को वर्ग नाम कैसे प्राप्त किया जाए।
newacct

@ समान, लेकिन सभी चर वर्ग उदाहरण नहीं हैं। यह भी कि प्रश्न वास्तव में जाँचने के बारे में था कि क्या प्रोग्रामर किस प्रकार की चीज़ों की तलाश कर रहा है, जबकि मैं केवल थोक के प्रकार का पता लगाने की उम्मीद कर रहा हूँ
जियारो


जवाबों:


284

स्विफ्ट 3 संस्करण:

type(of: yourObject)

8
मजेदार तथ्य। यह अंतर्निहित अलिखित वैकल्पिक के साथ काम नहीं करता है! यानी var myVar: SomeType!। संकलक त्रुटि "प्रकार के मूल्य कनवर्ट नहीं कर सकता 'SomeType! .Type' (उर्फ 'ImplicitlyUnwrappedOptional <SomeType> .Type') की उम्मीद तर्क प्रकार 'AnyClass' (उर्फ 'AnyObject.Type') संकलक को जोड़ने का सुझाव देता है as! AnyClassप्रकार है, लेकिन फिर बाद कुछ "EXC_BAD_INSTRUCTION" और अन्य jiberrish के साथ प्रोग्राम क्रैश हो जाता है, जिन्हें मैं समझ नहीं सकता।
लाइटनिंगस्ट्राइक

1
वास्तव में, यह स्वीकार किया जाना चाहिए कि स्विफ्ट 3 मौजूद है। धन्यवाद जेरेमी!
बायोमिकर

1
यदि आप विशिष्ट प्रकार के नाम की तलाश कर रहे हैं, जब प्रकार एक प्रोटोकॉल प्रकार का होता है, तो यह आपके लिए काम नहीं कर सकता है।
क्रिस प्रिंस

2
यदि आपके पास एक है Stringजो टाइप के रूप में पारित हो गया है Anyतो type(of:)आउटपुट होगा Any, नहीं String
स्कॉट्टीब्लाड्स

1
@SctyBlades तो क्या समाधान होगा। क्या आप प्रदान कर सकते हैं?
मुबीन मॉल

109

स्विफ्ट 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!")
    }

7
यह भी खूब रही। खबरदार कि अगर वस्तु को मिरर किया जा रहा है वैकल्पिक प्रकार का है, तो इसे गैर-वैकल्पिक प्रकार से तुलना करना विफल हो जाएगा। Stringऔर Optional(String)समान नहीं हैं।
थॉमस वर्बीक

1
वास्तव में मैं क्या देख रहा था, जानना चाहता था कि वस्तु का प्रकार क्या है
यूसुफ

क्या इस संदर्भ में एक प्रकार की तुलना है जो गैर-वैकल्पिक प्रकारों के खिलाफ वैकल्पिक की तुलना करते समय विफल नहीं होगी ?
क्रिस प्रिंस

यही मैं ढूंढ रहा था। शुक्रिया @Gudbergur
मुबीन मॉल

60

dynamicType.printClassNameकोड स्विफ्ट किताब में एक उदाहरण से है। ऐसा कोई तरीका नहीं है जिससे मैं सीधे कस्टम क्लास नाम को जान सकूं, लेकिन आप isनीचे दिखाए गए कीवर्ड का उपयोग करके एक इंस्टेंस प्रकार की जांच कर सकते हैं। यह उदाहरण यह भी दर्शाता है कि कस्टम क्लासनाम फ़ंक्शन को कैसे लागू किया जाए, यदि आप वास्तव में एक स्ट्रिंग के रूप में क्लास का नाम चाहते हैं।

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 पहले ही अपने स्वयं के वर्गनाम को लागू करते हैं। यदि आप कोको के साथ काम कर रहे हैं, तो आप इस संपत्ति का उपयोग कर सकते हैं।

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

2
अरे, यकीन नहीं है कि यह कब बदल गया, लेकिन जैसा कि एलेक्स प्रेट्ज़लाव ने बताया, व्यवहार बदल गया है।
जियाओरो

1
हाँ। स्विफ्ट 3.0 के रूप में, subjectTypeअब उपलब्ध नहीं है, और dynamicTypeसंकलक से एक पदावनत संदेश का कारण बनता है।
राफेल

41

Xcode 6.0.1 के रूप में (कम से कम, यकीन नहीं है कि जब उन्होंने इसे जोड़ा), तो आपका मूल उदाहरण अब काम करता है:

class MyClass {
    var count = 0
}

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

अपडेट करें:

मूल प्रश्न का उत्तर देने के लिए, आप वास्तव में सादे स्विफ्ट ऑब्जेक्ट के साथ ऑब्जेक्टिव-सी रनटाइम का सफलतापूर्वक उपयोग कर सकते हैं।

निम्नलिखित आज़माएँ:

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

ऐसा लगता है कि उन्होंने इसे एक उदाहरण के बजाय आपको देने के लिए बदल दिया है।
जियाआरो

@ जियारो, मैंने अपने उत्तर को इस बात से अपडेट किया कि मुझे क्या लगता है कि आप अपने मूल प्रश्न की तलाश में थे
एलेक्स प्रेट्ज़लाव

36

यदि आपको बस यह जांचने की आवश्यकता है कि चर प्रकार X का है, या कि यह किसी प्रोटोकॉल के अनुरूप है, तो आप निम्न में isया इसका उपयोग कर सकते हैं as?:

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

यह isKindOfClassओबज-सी में बराबर है।

और यह के बराबर है 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>
}

आपके उत्तर का दूसरा भाग गलत है। as?सशर्त कलाकारों के साथ 'अगर' चलें 'कथन भी ऐसा ही करता है isKindOfClass, बस यह भी बताता है कि कलाकारों को क्या परिणाम चाहिए।
18

समतुल्य isMemberOfClassस्थिति है object.dynamicType == ClassName.self
जावेद


10

स्विफ्ट 3.0 के लिए

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

स्विफ्ट 2.0 के लिए - 2.3

String(<Class-Name>)

1
मेरे लिए इस उत्तर के सही होने के बारे में महत्वपूर्ण बात यह है कि परिणामी स्ट्रिंग बिल्कुल कक्षा के नाम से मेल खाती है - इसलिए मैं इसका उपयोग NSManagedObject उपवर्ग से एक कोर डेटा इकाई नाम प्राप्त करने के लिए कर सकता हूं। मैंने स्विफ्ट 3 संस्करण का उपयोग किया।
केंडल हेल्मेस्सेट्टर गेलनर

8

यहाँ 2 तरीके हैं जो मैं इसे करने की सलाह देता हूं:

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

2
print( aShape is Square ), isऑपरेटर अधिक बेहतर है।
डॉनसॉन्ग

वस्तुओं के प्रकार प्राप्त करने के लिए मेरे लिए अच्छा समाधान।
निघासमाता

1

उपयोग के मामले पर निर्भर करता है। लेकिन मान लें कि आप अपने "चर" प्रकारों के साथ कुछ उपयोगी करना चाहते हैं। स्विफ्ट 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 या स्ट्रिंग हो सकते हैं। में .filter()शब्दकोश पर विधि, मैं, सही ढंग से मूल्यों और एक स्ट्रिंग के लिए केवल परीक्षण के लिए यकीन है कि मैं परीक्षण करने की जरूरत है जब यह एक स्ट्रिंग है आदि स्विच बयान इस सरल और सुरक्षित बनाता है! किसी भी प्रकार के वेरिएबल को 9 असाइन करके, यह इंट एक्जीक्यूट के लिए स्विच बनाता है। इसे बदलने का प्रयास करें:

   let eValue:Any = "home9"

..और फिर कोशिश करें। इस समय यह निष्पादित करता हैas String मामले को है।


1

यदि आपको "हमेशा सही / विफल" चेतावनी मिलती है, तो आपको उपयोग करने से पहले किसी को भी कास्ट करने की आवश्यकता हो सकती है is

(foo as Any) is SomeClass

0
//: 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.