Ich habe ein Array, das besteht AnyObject
. Ich möchte darüber iterieren und alle Elemente finden, die Array-Instanzen sind.
Wie kann ich in Swift überprüfen, ob ein Objekt von einem bestimmten Typ ist?
Ich habe ein Array, das besteht AnyObject
. Ich möchte darüber iterieren und alle Elemente finden, die Array-Instanzen sind.
Wie kann ich in Swift überprüfen, ob ein Objekt von einem bestimmten Typ ist?
Antworten:
Wenn Sie mit einem bestimmten Typ vergleichen möchten, können Sie Folgendes tun:
if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}
Sie können "as!" und das wird einen Laufzeitfehler auslösen, wenn obj
nicht vom Typ ist[String]
let stringArray = obj as! [String]
Sie können auch jeweils ein Element überprüfen:
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
}
}
?
nicht vorhanden ist? Es klingt wie as
und ?
wenn sie kombiniert werden Laufzeitüberprüfung durchführen. Wann wäre es angebracht, as
ohne zu verwenden ?
? Danke im Voraus.
as
ohne verwenden, ?
wenn Ihr Programm auf keinen Fall von dem Objekt wiederhergestellt werden kann, das nicht von diesem Typ ist, da das Programm sofort angehalten wird, wenn dies nicht der Fall ist. Mit der ?
in der if
Anweisung kann das Programm fortgesetzt werden.
?
in diesem Fall eine "generische" Typprüfung durchführen würde, wenn ja, zur if-Klausel, wenn nicht, zur else-Klausel. Ohne das ?
würde sonst nie eingegeben werden und wie Sie betonten, einen Laufzeitfehler verursachen. Danke noch einmal.
?
ermöglicht die Rückgabe der Zuweisung, nil
wodurch die if-Anweisung zurückgegeben wird false
und somit zur else-Anweisung durchfällt. Ich denke jedoch, dass die Erklärung beim Verständnis hilft, aber if let
tatsächlich ein Sonderfall im Compiler ist
In Swift 2.2 - 5 können Sie jetzt Folgendes tun:
if object is String
{
}
Dann filtern Sie Ihr Array:
let filteredArray = originalArray.filter({ $0 is Array })
Wenn Sie mehrere Typen überprüfen müssen:
switch object
{
case is String:
...
case is OtherClass:
...
default:
...
}
object
als String
Innenseite der Klammern verwenden (zumindest in Swift 2), während Sie dies mit der let
Lösung tun können.
object
im Block in Ordnung ist.
object.uppercaseString
weil der Typ der Variablen nicht in diesen Typ umgewandelt wird. Sie haben nur überprüft, dass das Objekt (auf das die Variable zeigt) ein istString
Wenn Sie nur wissen , ob ein Objekt ist ein Subtyp eines bestimmten Typs dann gibt es einen einfacheren Ansatz ist:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
func area (shape: Shape) -> Double {
if shape is Circle { ... }
else if shape is Rectangle { ... }
}
„Verwenden Sie den Typprüfungsoperator (is), um zu überprüfen, ob eine Instanz von einem bestimmten Unterklassentyp ist. Der Typprüfungsoperator gibt true zurück, wenn die Instanz von diesem Unterklassentyp ist, und false, wenn dies nicht der Fall ist. “ Auszug aus: Apple Inc. "Die schnelle Programmiersprache". iBooks .
Oben ist der Ausdruck "eines bestimmten Unterklassentyps" wichtig. Die Verwendung von is Circle
und is Rectangle
wird vom Compiler akzeptiert, da dieser Wert shape
als Shape
(eine Oberklasse von Circle
und Rectangle
) deklariert ist .
Wenn Sie primitive Typen verwenden, wäre die Oberklasse Any
. Hier ist ein Beispiel:
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"
is
noch funktionieren, wenn ich einen primitiven Typ in einem Array gespeichert hätte oder wenn das Array vom primitiven Typ ist ? Vielen Dank.
object
als deklarieren Any
. Mit einem Beispiel aktualisiert.
AnyObject
vorgeschlagen wird, eine Erwiderung erfolgt zu sein scheint, weil ich AnyObject
nicht von geerbt habe NSObject
. Wenn dies Any
anders ist, wäre dies in der Tat auch eine großartige Lösung. Vielen Dank.
Ich habe zwei Möglichkeiten:
if let thisShape = aShape as? Square
Oder:
aShape.isKindOfClass(Square)
Hier ist ein detailliertes Beispiel:
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")
}
Edit: 3 jetzt:
let myShape = Shape()
if myShape is Shape {
print("yes it is")
}
isKindOfClass
ist eine Methode des NSObject
Protokolls; Es sollte nur für Klassen funktionieren, die es übernehmen (alle Klassen, die von NSObject abstammen, sowie alle benutzerdefinierten Swift-Klassen, die es explizit übernehmen)
für swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Angenommen, drawTriangle ist eine Instanz von UIView. So prüfen Sie, ob drawTriangle vom Typ UITableView ist:
In Swift 3 ,
if drawTriangle is UITableView{
// in deed drawTriangle is UIView
// do something here...
} else{
// do something here...
}
Dies kann auch für von Ihnen definierte Klassen verwendet werden. Sie können dies verwenden, um Unteransichten einer Ansicht zu überprüfen.
Warum nicht die speziell für diese Aufgabe entwickelte Funktionalität nutzen?
let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)
Result: "Array<Any>"
Seien Sie gewarnt:
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)
Alle vier letzten Zeilen geben true zurück. Dies liegt daran, dass Sie eingeben
var r1:CGRect = CGRect()
print(r1 is String)
... es wird natürlich "false" ausgegeben, aber eine Warnung besagt, dass die Umwandlung von CGRect in String fehlschlägt. Einige Typen werden also überbrückt, und das Schlüsselwort 'is' ruft eine implizite Umwandlung auf.
Sie sollten besser eines davon verwenden:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Wenn Sie die Klasse aufgrund des nicht verwendeten definierten Werts (let someVariable ...) nur überprüfen möchten, ohne eine Warnung zu erhalten, können Sie das let-Zeug einfach durch einen Booleschen Wert ersetzen:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode schlug dies vor, als ich den let-Weg verwendete und den definierten Wert nicht verwendete.
Warum nicht so etwas benutzen?
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
}
in Swift 3.
Swift 4.2, In meinem Fall mit der isKind-Funktion.
isKind (of :) Gibt einen booleschen Wert zurück, der angibt, ob der Empfänger eine Instanz einer bestimmten Klasse oder eine Instanz einer Klasse ist, die von dieser Klasse erbt.
let items : [AnyObject] = ["A", "B" , ... ]
for obj in items {
if(obj.isKind(of: NSString.self)){
print("String")
}
}
Lesen Sie mehr https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418511-iskind
Nur der Vollständigkeit halber basierend auf der akzeptierten Antwort und einigen anderen:
let items : [Any] = ["Hello", "World", 1]
for obj in items where obj is String {
// obj is a String. Do something with str
}
Sie können aber auch ( compactMap
auch die Werte "abbilden", was filter
nicht der Fall ist):
items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }
Und eine Version mit 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
}
}
Aber bleiben Sie bei der Frage, um zu überprüfen, ob es sich um ein Array handelt (dh [String]
):
let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]
for obj in items {
if let stringArray = obj as? [String] {
print("\(stringArray)")
}
}
Oder allgemeiner (siehe diese andere Frage Antwort ):
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")
}
}
as?
gibt Ihnen nicht immer das erwartete Ergebnis , da as
nicht testen , ob ein Datentyp ist von einer bestimmten Art , sondern nur dann , wenn ein Datentyp werden kann umgewandelt oder als dargestellt spezifische Art.
Betrachten Sie diesen Code zum Beispiel:
func handleError ( error: Error ) {
if let nsError = error as? NSError {
Jeder dem Error
Protokoll entsprechende Datentyp kann in ein NSError
Objekt konvertiert werden, sodass dies immer erfolgreich ist . Dies bedeutet jedoch nicht, dass error
es sich tatsächlich um ein NSError
Objekt oder eine Unterklasse davon handelt.
Eine korrekte Typprüfung wäre:
func handleError ( error: Error ) {
if type(of: error) == NSError.self {
Dies prüft jedoch nur den genauen Typ. Wenn Sie auch eine Unterklasse von einschließen möchten NSError
, sollten Sie Folgendes verwenden:
func handleError ( error: Error ) {
if error is NSError.Type {
Wenn Sie eine Antwort wie diese haben:
{
"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
}
und Sie möchten nach Werten is_stucked
suchen, die als AnyObject gelesen werden. Alles, was Sie tun müssen, ist dies
if let isStucked = response["is_stucked"] as? Bool{
if isStucked{
print("is Stucked")
}
else{
print("Not Stucked")
}
}
Wenn Sie nicht wissen, dass Sie in der Antwort vom Server ein Array von Wörterbüchern oder ein einzelnes Wörterbuch erhalten, müssen Sie überprüfen, ob das Ergebnis ein Array enthält oder nicht.
In meinem Fall immer eine Reihe von Wörterbüchern erhalten, außer einmal. Um damit umzugehen, habe ich den folgenden Code für Swift 3 verwendet.
if let str = strDict["item"] as? Array<Any>
Hier als? Array prüft, ob der erhaltene Wert ein Array (von Wörterbuchelementen) ist. In anderen Fällen können Sie damit umgehen, ob es sich um ein einzelnes Wörterbuchelement handelt, das nicht in einem Array gespeichert ist.
Swift 5.2 & Xcode Version: 11.3.1 (11C504)
Hier ist meine Lösung zur Überprüfung des Datentyps:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
Ich hoffe es hilft dir.