Tengo una matriz compuesta de AnyObject. Quiero iterar sobre él y encontrar todos los elementos que son instancias de matriz.
¿Cómo puedo verificar si un objeto es de un tipo dado en Swift?
Tengo una matriz compuesta de AnyObject. Quiero iterar sobre él y encontrar todos los elementos que son instancias de matriz.
¿Cómo puedo verificar si un objeto es de un tipo dado en Swift?
Respuestas:
Si desea verificar un tipo específico, puede hacer lo siguiente:
if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}
Puedes usar "como!" y eso arrojará un error de tiempo de ejecución si objno es de tipo[String]
let stringArray = obj as! [String]
También puede verificar un elemento a la vez:
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
}
}
?no está presente? Suena como asy ?cuando se combina realizará una verificación de tiempo de ejecución. ¿Cuándo sería apropiado usar assin ?? Gracias por adelantado.
assin el ?si no hay forma de que su programa pueda recuperarse del objeto que no es de ese tipo porque el programa se detendrá inmediatamente si no lo es. El uso de ?en la ifdeclaración permite que el programa continúe.
?en este caso realizaría una verificación de tipo "genérico", en caso afirmativo, a la cláusula if, si no, a la cláusula else. Sin lo ?contrario, nunca se ingresaría y, como señaló, provocará un error de tiempo de ejecución. Gracias de nuevo.
?permite la asignación para volver nilhaciendo que la sentencia if para el retorno falsey, por tanto, que cae a través de la sentencia else. Sin embargo, creo que la explicación ayuda con el entendimiento, pero if leten realidad es un caso especial en el compilador
En Swift 2.2 - 5 ahora puede hacer:
if object is String
{
}
Luego, para filtrar su matriz:
let filteredArray = originalArray.filter({ $0 is Array })
Si tiene varios tipos para verificar:
switch object
{
case is String:
...
case is OtherClass:
...
default:
...
}
objectcomo Stringdentro de las llaves (al menos en Swift 2), mientras que con la letsolución puede hacerlo.
objecten el bloque está bien.
object.uppercaseStringporque el tipo de la variable no está fundido a ese tipo, simplemente verificó que el objeto (señalado por la variable) es unString
Si solo desea saber si un objeto es un subtipo de un tipo dado, entonces hay un enfoque más simple:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
func area (shape: Shape) -> Double {
if shape is Circle { ... }
else if shape is Rectangle { ... }
}
“Utilice el operador de verificación de tipo (is) para verificar si una instancia es de cierto tipo de subclase. El operador de verificación de tipo devuelve verdadero si la instancia es de ese tipo de subclase y falso si no lo es ". Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks .
En lo anterior, la frase 'de cierto tipo de subclase' es importante. El compilador acepta el uso de is Circley is Rectangleporque ese valor shapese declara como Shape(una superclase de Circley Rectangle).
Si está utilizando tipos primitivos, la superclase sería Any. Aquí hay un ejemplo:
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"
istodavía funcionaría aquí? Gracias.
objectcomo Any. Actualizado con un ejemplo.
AnyObjectse sugiere, parece haber sido replicada debido a que AnyObjectno heredó de NSObject. Si Anyes diferente, entonces esta sería una gran solución también. Gracias.
Tengo 2 formas de hacerlo:
if let thisShape = aShape as? Square
O:
aShape.isKindOfClass(Square)
Aquí hay un ejemplo detallado:
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")
}
Editar: 3 ahora:
let myShape = Shape()
if myShape is Shape {
print("yes it is")
}
isKindOfClasses un método del NSObjectprotocolo; solo debería funcionar para las clases que lo adoptan (todas las clases que descienden de NSObject, más cualquier clase personalizada de Swift que lo adopte explícitamente)
para swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Asumir dibujar Triángulo es una instancia de UIView. Para verificar si drawTriangle es del tipo UITableView:
En Swift 3 ,
if drawTriangle is UITableView{
// in deed drawTriangle is UIView
// do something here...
} else{
// do something here...
}
Esto también podría usarse para clases definidas por usted mismo. Puede usar esto para verificar las subvistas de una vista.
¿Por qué no utilizar la funcionalidad integrada creada especialmente para esta tarea?
let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)
Result: "Array<Any>"
Ten cuidado con esto:
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)
Las cuatro últimas líneas devuelven verdadero, esto se debe a que si escribe
var r1:CGRect = CGRect()
print(r1 is String)
... imprime "falso", por supuesto, pero una Advertencia dice que falla la transmisión de CGRect a String. Por lo tanto, se conectan algunos tipos, y la palabra clave 'is' llama un molde implícito.
Deberías usar uno de estos:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Si solo desea verificar la clase sin recibir una advertencia debido al valor definido no utilizado (let someVariable ...), simplemente puede reemplazar el material let con un valor booleano:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode propuso esto cuando utilicé let way y no utilicé el valor definido.
¿Por qué no usar algo como esto?
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
}
en Swift 3.
Swift 4.2, en mi caso, usando la función isKind.
isKind (of :) Devuelve un valor booleano que indica si el receptor es una instancia de una clase dada o una instancia de cualquier clase que herede de esa clase.
let items : [AnyObject] = ["A", "B" , ... ]
for obj in items {
if(obj.isKind(of: NSString.self)){
print("String")
}
}
Leer más https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418511-iskind
Solo en aras de la exhaustividad basada en la respuesta aceptada y algunas otras:
let items : [Any] = ["Hello", "World", 1]
for obj in items where obj is String {
// obj is a String. Do something with str
}
Pero también puede ( compactMaptambién "asigna" los valores que filterno):
items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }
Y una versión usando 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
}
}
Pero atendiendo a la pregunta, para verificar si es una matriz (es decir [String]):
let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]
for obj in items {
if let stringArray = obj as? [String] {
print("\(stringArray)")
}
}
O de manera más general (vea esta otra pregunta respuesta )
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?no siempre le dará el resultado esperado porque asno prueba si un tipo de datos es de un tipo específico, sino solo si un tipo de datos se puede convertir o representar como un tipo específico.
Considere este código, por ejemplo:
func handleError ( error: Error ) {
if let nsError = error as? NSError {
Cada tipo de datos conforme al Errorprotocolo se puede convertir en un NSErrorobjeto, por lo que esto siempre tendrá éxito . Sin embargo, eso no significa que errorde hecho sea un NSErrorobjeto o una subclase de él.
Una verificación de tipo correcta sería:
func handleError ( error: Error ) {
if type(of: error) == NSError.self {
Sin embargo, esto verifica solo el tipo exacto. Si desea incluir también la subclase de NSError, debe usar:
func handleError ( error: Error ) {
if error is NSError.Type {
Si tiene una respuesta como esta:
{
"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
}
y desea verificar el valor is_stuckedque se leerá como AnyObject, todo lo que tiene que hacer es esto
if let isStucked = response["is_stucked"] as? Bool{
if isStucked{
print("is Stucked")
}
else{
print("Not Stucked")
}
}
Si no sabe que obtendrá una matriz de diccionarios o un solo diccionario en la respuesta del servidor, debe verificar si el resultado contiene una matriz o no.
En mi caso, siempre recibo una serie de diccionarios, excepto una vez. Entonces, para manejar eso, utilicé el siguiente código para Swift 3.
if let str = strDict["item"] as? Array<Any>
¿Aquí como? La matriz verifica si el valor obtenido es matriz (de elementos del diccionario). En otro caso, puede manejar si es un elemento de diccionario único que no se mantiene dentro de una matriz.
Swift 5.2 y Versión Xcode: 11.3.1 (11C504)
Aquí está mi solución de verificar el tipo de datos:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
Espero que te ayude.