У мене є масив, який складається AnyObject. Я хочу перебрати його і знайти всі елементи, які є екземплярами масиву.
Як я можу перевірити, чи є об'єкт даного типу в Swift?
У мене є масив, який складається AnyObject. Я хочу перебрати його і знайти всі елементи, які є екземплярами масиву.
Як я можу перевірити, чи є об'єкт даного типу в Swift?
Відповіді:
Якщо ви хочете перевірити певний тип, ви можете зробити наступне:
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без ?? Заздалегідь спасибі.
asбез того, ?якщо немає можливості, щоб ваша програма могла відновитись із об'єкта, який не має такого типу, оскільки програма негайно зупиниться, якщо її немає. Використання ?в ifоператорі дозволяє програмі продовжувати роботу.
?цього випадку виконає перевірку типу "загального", якщо так, до пункту "if", якщо ні - до "іншого". Без ?іншого ніколи не буде введено, і, як ви вказали, викликати помилку виконання. Знову дякую.
?Дозволяє присвоювання повернутися nilвикликаючи якщо заяву повернення falseі , отже , провалюючись в іншу заяву. Однак я думаю, що пояснення допомагає з розумінням, але if letнасправді це особливий випадок у компіляторі
У Swift 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внутрішню дужку (принаймні у Swift 2), тоді як з letрішенням ви можете це зробити.
objectв блоці добре.
object.uppercaseStringтому що тип змінної не приводиться до цього типу, ви просто перевірили, що об'єкт (вказаний змінною)String
Якщо ви хочете лише знати, чи об’єкт є підтипом даного типу, тоді існує більш простий підхід:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
func area (shape: Shape) -> Double {
if shape is Circle { ... }
else if shape is Rectangle { ... }
}
“Використовуйте оператор перевірки типу (є), щоб перевірити, чи є примірник певного типу підкласу. Оператор перевірки типу повертає true, якщо екземпляр цього типу підкласу, а false, якщо його немає. " Уривок: 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"
isусе ще працюватиме тут? Дякую.
objectяк Any. Оновлено прикладом.
AnyObjectпропонується, схоже, було відмовлено у зв'язку з тим, що AnyObjectне успадковувались від NSObject. Якщо Anyінакше, то це було б насправді і чудовим рішенням. Дякую.
У мене є два способи це зробити:
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")
}
isKindOfClass- метод NSObjectпротоколу; він повинен працювати лише для класів, які приймають його (усі класи, що походять від NSObject, плюс будь-який спеціальний клас Swift, який явно приймає його)
для swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Припустимо drawTriangle - це примірник UIView. Щоб перевірити, чи drawTriangle має тип UITableView:
У Swift 3 ,
if drawTriangle is UITableView{
// in deed drawTriangle is UIView
// do something here...
} else{
// do something here...
}
Це також може бути використане для занять, визначених вами. Ви можете скористатися цією функцією, щоб перевірити підгляди подання.
Чому б не використати вбудований функціонал, побудований спеціально для цього завдання?
let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)
Result: "Array<Any>"
Попереджуйте про це:
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 до String не вдається. Таким чином, якийсь тип з'єднаний, а ключове слово "є" викликає неявний склад.
Вам краще скористатися одним із таких:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Якщо ви просто хочете перевірити клас, не отримуючи попередження через невикористане визначене значення (нехай деякіVariable ...), ви можете просто замінити пусті речі булевими:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode запропонував це, коли я використовував пусковий шлях і не використовував визначене значення.
Чому б не використати щось подібне
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
}
у Swift 3.
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/1418511-iskind
Просто задля повноти на основі прийнятої відповіді та деяких інших:
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")
}
}
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 {
Якщо у вас є така відповідь:
{
"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")
}
}
Якщо ви не знаєте, що у відповіді від сервера ви отримаєте масив словників чи єдиний словник, вам потрібно перевірити, чи містить результат масив чи ні.
У моєму випадку завжди отримується масив словників, крім одного разу. Отже, для обробки я використовував наведений нижче код для швидкого 3.
if let str = strDict["item"] as? Array<Any>
Тут як? Масив перевіряє, чи є отримане значення масивом (елементів словника). В іншому випадку ви можете обробити, якщо це єдиний елемент словника, який не зберігається всередині масиву.
Версія Swift 5.2 та Xcode: 11.3.1 (11C504)
Ось моє рішення щодо перевірки типу даних:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
Сподіваюся, це допоможе тобі.