यह जाँचना कि क्या कोई वस्तु स्विफ्ट में दिया गया प्रकार है


267

मेरे पास एक ऐसा सरणी है जो बना है AnyObject। मैं इस पर पुनरावृति करना चाहता हूं, और उन सभी तत्वों को ढूंढता हूं जो सरणी उदाहरण हैं।

यदि कोई वस्तु किसी प्रकार की स्विफ्ट में है, तो मैं कैसे जांच सकता हूं?


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

मैंने इस प्रश्न को stackoverflow.com/q/24093433 से अलग करने के लिए संपादित किया है , जिसे मैं फिर से शुरू करने के लिए मतदान कर रहा हूं। वे दोनों उपयोगी, समान, प्रश्न हैं, लेकिन उत्तर काफी अलग हैं, इसलिए उन्हें अलग रखना उपयोगी होगा।
जेरेमी बैंक्स

जवाबों:


304

यदि आप एक विशिष्ट प्रकार के खिलाफ जांच करना चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

if let stringArray = obj as? [String] {
    // obj is a string array. Do something with stringArray
}
else {
    // obj is not a string array
}

आप "के रूप में" का उपयोग कर सकते हैं! और जो objटाइप का नहीं है तो रनटाइम एरर फेंक देगा[String]

let stringArray = obj as! [String]

आप एक समय में एक तत्व भी देख सकते हैं:

let items : [Any] = ["Hello", "World"]
for obj in items {
   if let str = obj as? String {
      // obj is a String. Do something with str
   }
   else {
      // obj is not a String
   }
}

जब ?मौजूद नहीं है तो केवल रनटाइम त्रुटि और संकलन समय त्रुटि क्यों होगा । ऐसा लगता है asऔर ?जब संयुक्त रनटाइम चेक करेगा। कब asबिना उपयोग करना उचित होगा ?? अग्रिम में धन्यवाद।
उन्हेलिग

@Unheilig आप केवल का उपयोग करना चाहिए asबिना ?अगर कोई तरीका है अपने कार्यक्रम से वस्तु क्योंकि कार्यक्रम तुरंत अगर यह नहीं है रुक जाएगा उस प्रकार के नहीं किया जा रहा ठीक हो सकता है। बयान ?में उपयोग करने ifसे कार्यक्रम जारी रह सकता है।
ड्रूग

प्रतिक्रिया के लिए धन्यवाद। अगर मैं गलत हूं तो मुझे सुधारें: मैंने सोचा कि ?इस मामले में उपयोग करने से "सामान्य" प्रकार की जांच होगी, यदि हां, यदि खंड के लिए, यदि नहीं, तो अन्य खंड के लिए। बिना ?दूसरे को कभी दर्ज नहीं किया जाएगा और जैसा कि आपने बताया कि एक रनटाइम त्रुटि है। एक बार फिर धन्यवाद।
उन्हेलिग

@ यूनीलीग आई एम सॉरी, मुझे समझ नहीं आ रहा है कि आप क्या कह रहे हैं / पूछ रहे हैं। यदि कथन वापस लौटने के लिए और इसलिए उसी कथन के माध्यम से गिरने के कारण ?असाइनमेंट वापस करने की अनुमति देता है । हालाँकि, मुझे लगता है कि स्पष्टीकरण समझ में मदद करता है, लेकिन वास्तव में संकलक में एक विशेष मामला हैnilfalseif let
drewag

1
@ यूनीलिग सही, आप वैर का उपयोग कर सकते हैं यदि आप उस स्थानीय दायरे में रहते हुए मूल्य को संशोधित करने में सक्षम होना चाहते हैं (उन परिवर्तनों का दायरा प्रभावित नहीं होगा)
drewag

202

में स्विफ्ट 2.2 - 5 तुम अब क्या कर सकते हैं:

if object is String
{
}

फिर अपने सरणी को फ़िल्टर करने के लिए:

let filteredArray = originalArray.filter({ $0 is Array })

यदि आपके पास जांच करने के लिए कई प्रकार हैं:

    switch object
    {
    case is String:
        ...

    case is OtherClass:
        ...

    default:
        ...
    }

यह समाधान में कम है, लेकिन यह एक नुकसान है: यदि आप उपयोग नहीं कर सकते objectएक के रूप में String, (स्विफ्ट 2 में कम से कम) ब्रेसिज़ के अंदर है, जबकि साथ letसमाधान आप यह कर सकते हैं।
फेरन मायलिनच

@FerranMaylinch समझ में नहीं आता है कि आप का क्या मतलब है क्योंकि objectब्लॉक में उपयोग करना ठीक है।
अर्थ-मायने

@ अर्थ-मामले जैसे आप ऐसा करने में सक्षम नहीं होंगे object.uppercaseStringक्योंकि उस प्रकार का चर उस प्रकार से नहीं डाला जाता है, आपने अभी जांचा है कि वस्तु (चर द्वारा इंगित) एक हैString
फेरन मायलिनच

यदि आप अपने वर्ग प्रकार की जांच कर रहे हैं तो आप ऐसा कैसे कर सकते हैं? यदि आपके पास केवल एक चर है, तो आपको एक वर्ग प्रकार प्राप्त करने की आवश्यकता है?
एलेक्स ज़ावाटोन

152

आप केवल तब एक वस्तु जानना चाहते हैं है एक दिया प्रकार का एक उप-प्रकार फिर वहाँ एक सरल तरीका है:

class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}

func area (shape: Shape) -> Double {
  if shape is Circle { ... }
  else if shape is Rectangle { ... }
}

“एक निश्चित उपवर्ग प्रकार का है या नहीं यह जाँचने के लिए टाइप चेक ऑपरेटर (है) का उपयोग करें। यदि जाँचकर्ता ऑपरेटर सही है, तो उदाहरण उस उपवर्ग प्रकार का है और यदि वह नहीं है तो गलत है। " इसके अंश: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।"iBooks

उपरोक्त वाक्यांश में 'एक निश्चित उपवर्ग प्रकार' महत्वपूर्ण है। के उपयोग is Circleऔर is Rectangleसंकलक द्वारा स्वीकार किया जाता है, क्योंकि है कि मूल्य shapeके रूप में घोषित किया जाता है Shape(के एक सुपर क्लास CircleऔरRectangle )।

यदि आप आदिम प्रकारों का उपयोग कर रहे हैं, तो सुपरक्लास होगा Any। यहाँ एक उदाहरण है:

 21> func test (obj:Any) -> String {
 22.     if obj is Int { return "Int" }
 23.     else if obj is String { return "String" }
 24.     else { return "Any" }
 25. } 
 ...  
 30> test (1)
$R16: String = "Int"
 31> test ("abc")
$R17: String = "String"
 32> test (nil)
$R18: String = "Any"

2
क्या होगा यदि मैंने एक आदिम प्रकार को एक सरणी में संग्रहीत किया है या यदि सरणी आदिम प्रकार में से एक है, तब isभी यहां काम करेगा ? धन्यवाद।
उन्हेलिग

यदि आप यह घोषणा करते यह काम करना चाहिए objectके रूप में Any। एक उदाहरण के साथ अपडेट किया गया।
गोयनर

जवाब के लिए धन्यवाद। यह आशाजनक लग रहा है। मेरा एकमात्र संदेह यह है कि नीचे दिए गए उत्तर के अनुसार, जिसमें AnyObjectसुझाव दिया गया है, ऐसा लगता है कि AnyObjectविरासत में नहीं मिलने के कारण बदला गया है NSObject। यदि Anyअलग है, तो यह वास्तव में एक महान समाधान होगा। धन्यवाद।
उन्नीलीग

21

मेरे पास इसे करने के 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")
}

संपादित करें: 3 अब:

let myShape = Shape()
if myShape is Shape {
    print("yes it is")
}

1
isKindOfClassNSObjectप्रोटोकॉल की एक विधि है ; इसे केवल उन वर्गों के लिए काम करना चाहिए जो इसे अपनाते हैं (NSObject से उतरने वाली सभी कक्षाएं, साथ ही कोई भी कस्टम स्विफ्ट क्लास जो इसे स्पष्ट रूप से अपनाती है)
निकोलस मिरी


9

ड्राट्राइंगल मान लें का एक उदाहरण है। जाँच करें कि क्या ड्राट्रिंज UITableView प्रकार का है:

में स्विफ्ट 3 ,

if drawTriangle is UITableView{
    // in deed drawTriangle is UIView
    // do something here...
} else{
    // do something here...
}

यह भी अपने आप से परिभाषित वर्गों के लिए इस्तेमाल किया जा सकता है। आप इसका उपयोग किसी दृश्य के साक्षात्कार की जांच करने के लिए कर सकते हैं।


5

इस कार्य के लिए विशेष रूप से निर्मित कार्यक्षमता में निर्मित का उपयोग क्यों नहीं करते हैं?

let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)

Result: "Array<Any>"

प्रकार () फ़ंक्शन सरल है
:)

5

इस बारे में चेतावनी दें:

var string = "Hello" as NSString
var obj1:AnyObject = string
var obj2:NSObject = string

print(obj1 is NSString)
print(obj2 is NSString)
print(obj1 is String)
print(obj2 is String) 

अंतिम चार पंक्तियों में से सभी सही हैं, ऐसा इसलिए है क्योंकि यदि आप टाइप करते हैं

var r1:CGRect = CGRect()
print(r1 is String)

... यह निश्चित रूप से "गलत" छापता है, लेकिन एक चेतावनी कहती है कि CGRect से स्ट्रिंग तक कास्ट विफल हो जाता है। तो कुछ प्रकारों को ब्रिज किया जाता है, ans 'is' कीवर्ड एक निहित कास्ट कहलाता है।

आपको इनमें से किसी एक का बेहतर उपयोग करना चाहिए:

myObject.isKind(of: MyClass.self)) 
myObject.isMember(of: MyClass.self))

2

यदि आप अप्रयुक्त परिभाषित मूल्य के कारण चेतावनी प्राप्त किए बिना कक्षा की जाँच करना चाहते हैं (someVariable ...), तो आप बस एक बूलियन के साथ लेट सामान को बदल सकते हैं:

if (yourObject as? ClassToCompareWith) != nil {
   // do what you have to do
}
else {
   // do something else
}

Xcode ने यह प्रस्तावित किया जब मैंने लेट का इस्तेमाल किया और परिभाषित मूल्य का उपयोग नहीं किया।


2

क्यों न इस तरह से कुछ इस्तेमाल किया जाए

fileprivate enum types {
    case typeString
    case typeInt
    case typeDouble
    case typeUnknown
}

fileprivate func typeOfAny(variable: Any) -> types {
    if variable is String {return types.typeString}
    if variable is Int {return types.typeInt}
    if variable is Double {return types.typeDouble}
    return types.typeUnknown
}

स्विफ्ट 3 में।


2

Swift 4.2, मेरे मामले में, isKind फ़ंक्शन का उपयोग कर रहा है।

isKind (of :) का एक बूलियन मान लौटाता है जो बताता है कि क्या रिसीवर किसी दिए गए वर्ग का उदाहरण है या उस वर्ग से प्राप्त किसी भी वर्ग का उदाहरण है।

  let items : [AnyObject] = ["A", "B" , ... ]
  for obj in items {
    if(obj.isKind(of: NSString.self)){
      print("String")
    }
  }

रीडमोर https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418525-bind


1
वह स्विफ्ट नहीं है। यह कोको है और केवल वहीं काम करता है जहां यह उद्देश्य सी। के लिए काम करेगा
मैट

1

myObject as? Stringरिटर्न nilअगर myObjectएक नहीं है String। अन्यथा, यह एक रिटर्न देता है String?, इसलिए आप स्ट्रिंग को स्वयं के साथ एक्सेस कर सकते हैं myObject!, या इसे myObject! as Stringसुरक्षित रूप से डाल सकते हैं।


1

स्विफ्ट 3:

class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}

if aShape.isKind(of: Circle.self) {
}

1

बस स्वीकृत उत्तर और कुछ अन्य के आधार पर पूर्णता के लिए:

let items : [Any] = ["Hello", "World", 1]

for obj in items where obj is String {
   // obj is a String. Do something with str
}

लेकिन आप उन compactMapमूल्यों को भी "मैप" कर सकते हैं जो filterनहीं करते):

items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }

और एक संस्करण का उपयोग कर switch:

for obj in items {
    switch (obj) {
        case is Int:
           // it's an integer
        case let stringObj as String:
           // you can do something with stringObj which is a String
        default:
           print("\(type(of: obj))") // get the type
    }
}

लेकिन यह एक सरणी (यानी [String]) है या नहीं , यह जांचने के लिए, चिपके रहना :

let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]

for obj in items {
  if let stringArray = obj as? [String] {
    print("\(stringArray)")
  }
}

या अधिक सामान्यतः ( इस अन्य प्रश्न का उत्तर देखें ):

for obj in items {
  if obj is [Any] {
    print("is [Any]")
  }

  if obj is [AnyObject] {
    print("is [AnyObject]")
  }

  if obj is NSArray {
    print("is NSArray")
  }
}

1

as?हमेशा आपको अपेक्षित परिणाम नहीं मिलेगा क्योंकि asयदि कोई डेटा प्रकार एक विशिष्ट प्रकार का नहीं है, तो परीक्षण करता है , लेकिन केवल यदि डेटा प्रकार को विशिष्ट प्रकार में परिवर्तित या प्रस्तुत किया जा सकता है ।

उदाहरण के लिए इस कोड पर विचार करें:

func handleError ( error: Error ) {
    if let nsError = error as? NSError {

Errorप्रोटोकॉल के अनुरूप हर डेटा प्रकार को एक NSErrorऑब्जेक्ट में बदला जा सकता है , इसलिए यह हमेशा सफल होगा । फिर भी इसका मतलब यह नहीं है कि errorयह वास्तव में एक NSErrorवस्तु या एक उपवर्ग है।

एक सही प्रकार की जाँच होगी:

func handleError ( error: Error ) {
    if type(of: error) == NSError.self {

हालाँकि, यह केवल सटीक प्रकार के लिए जाँच करता है। यदि आप भी उपवर्ग शामिल करना चाहते हैं NSError, तो आपको उपयोग करना चाहिए:

func handleError ( error: Error ) {
    if error is NSError.Type {

0

यदि आपके पास इस तरह की प्रतिक्रिया है:

{
  "registeration_method": "email",
  "is_stucked": true,
  "individual": {
    "id": 24099,
    "first_name": "ahmad",
    "last_name": "zozoz",
    "email": null,
    "mobile_number": null,
    "confirmed": false,
    "avatar": "http://abc-abc-xyz.amazonaws.com/images/placeholder-profile.png",
    "doctor_request_status": 0
  },
  "max_number_of_confirmation_trials": 4,
  "max_number_of_invalid_confirmation_trials": 12
}

और आप मान के लिए जांच करना चाहते is_stuckedहैं जिसे AnyObject के रूप में पढ़ा जाएगा, आपको बस इतना करना है

if let isStucked = response["is_stucked"] as? Bool{
  if isStucked{
      print("is Stucked")
  }
  else{
      print("Not Stucked")
 }
}

0

यदि आप नहीं जानते हैं कि आपको सर्वर से प्रतिक्रिया में शब्दकोशों या एकल शब्दकोश की एक सरणी मिलेगी, तो आपको यह जांचना होगा कि परिणाम में कोई सरणी है या नहीं।
मेरे मामले में हमेशा एक बार छोड़कर केवल शब्दकोशों की एक सरणी प्राप्त होती है। इसलिए, यह संभालने के लिए कि मैंने स्विफ्ट 3 के लिए नीचे दिए गए कोड का उपयोग किया है।

if let str = strDict["item"] as? Array<Any>

यहाँ के रूप में? Array यह जाँचता है कि प्राप्त मान अरै है (डिक्शनरी आइटम्स का)। किसी अन्य मामले में आप संभाल सकते हैं यदि यह एकल शब्दकोष है जो किसी ऐरे के अंदर नहीं रखा गया है।


0

स्विफ्ट 5.2 और Xcode संस्करण: 11.3.1 (11C504)

यहाँ डेटा प्रकार की जाँच का मेरा समाधान है:

 if let typeCheck = myResult as? [String : Any] {
        print("It's Dictionary.")
    } else { 
        print("It's not Dictionary.") 
    }

मुझे आशा है कि यह आपकी मदद करेगा।


जब एक पुराने प्रश्न का उत्तर दिया जाता है, तो आपका उत्तर अन्य StackOverflow उपयोगकर्ताओं के लिए बहुत अधिक उपयोगी होगा यदि आपने कुछ संदर्भ को यह समझाने के लिए शामिल किया कि आपका उत्तर कैसे मदद करता है, विशेष रूप से उस प्रश्न के लिए जो पहले से ही स्वीकृत उत्तर है। देखें: कैसे मैं एक अच्छा जवाब लिख सकता हूं
डेविड बक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.