Проверка, является ли объект заданным типом в Swift

217

У меня есть массив, состоящий из AnyObject. Я хочу перебрать его и найти все элементы, которые являются экземплярами массива.

Как проверить, является ли объект данного типа в Swift?

  • 0
    Ваш вопрос спрашивает о том, чтобы найти тип данного объекта, но вы приняли ответ, который способен только проверить, принадлежит ли объект данному типу. Я предлагаю вам отредактировать свой вопрос именно так, иначе многие читатели будут недовольны ответом, который вы приняли. (Все остальные ответы похожи, поэтому, к счастью, вам не нужно беспокоиться о том, чтобы сделать их недействительными, сузив свой вопрос.)
  • 0
    Я отредактировал этот вопрос, чтобы устранить неоднозначность с сайта stackoverflow.com/q/24093433 , который я голосую, чтобы вновь открыть. Они оба полезны, похожи, вопросы, но ответы весьма различны, поэтому было бы полезно разделить их.
Показать ещё 1 комментарий
Теги:
type-inference
typechecking

14 ответов

239
Лучший ответ

Если вы хотите проверить конкретный тип, вы можете сделать следующее:

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
   }
}
  • 0
    Почему это только выдает ошибку времени выполнения, а не ошибку времени компиляции, когда ? нет Звучит as и ? при объединении выполнит проверку во время выполнения. Когда было бы целесообразно использовать as без ? ? Заранее спасибо.
  • 0
    @ Unheilig Вы должны использовать только as без ? если ваша программа не сможет восстановить объект, не относящийся к этому типу, потому что программа немедленно остановится, если это не так. Используя ? в операторе if программа может продолжаться.
Показать ещё 9 комментариев
143

Если вы хотите узнать только, является ли объект подтипом данного типа, тогда существует более простой подход:

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

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

"Используйте оператор проверки типа (is), чтобы проверить, является ли экземпляр определенного  тип подкласса. Оператор проверки типа возвращает true, если экземпляр имеет  этот тип подкласса и false, если это не так ". Excerpt From: 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 еще работать здесь? Благодарю.
  • 0
    Это должно работать, если вы объявите object как Any . Обновлено с примером.
Показать ещё 1 комментарий
139

В Swift 2.2 - 4.0.3 теперь вы можете делать:

if object is String
{
}

Затем для фильтрации вашего массива:

let filteredArray = originalArray.filter({ $0 is Array })
  • 11
    Это должен быть принят ответ.
  • 9
    Вот почему полезно прочитать еще пару ответов, помимо принятого. :)
Показать ещё 5 комментариев
19

У меня есть два способа сделать это:

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")
}
  • 0
    Это лучший ответ в этой теме.
  • 1
    isKindOfClass - это метод протокола NSObject ; он должен работать только для классов, которые его принимают (все классы, происходящие из NSObject, плюс любой пользовательский класс Swift, который принимает его явно)
Показать ещё 1 комментарий
11

для swift4:

if obj is MyClass{
    // then object type is MyClass Type
}
  • 0
    это применимо и к Swift 2 и 3.
  • 0
    я не уверен, но если это я буду редактировать этот ответ, я постараюсь в ближайшее время, и большое спасибо за ваше предложение
9

Предположим, что drawTriangle является экземпляром UIView. Чтобы проверить, имеет ли drawTriangle тип UITableView:

В Swift 3,

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

Это также может использоваться для классов, определенных вами. Вы можете использовать это, чтобы проверить subviews представления.

  • 0
    отличный ответ
4

Будьте предупреждены об этом:

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) 

Все четыре последние строки возвращают true, потому что, если вы введете

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

... конечно, он печатает "ложь", но предупреждение указывает, что сбрасывается Cast из CGRect в String. Таким образом, некоторый тип связан с мостом, а ключевое слово 'is' вызывает неявное преобразование.

Вам следует использовать один из следующих вариантов:

myObject.isKind(of: MyClass.self)) 
myObject.isMember(of: MyClass.self))
  • 0
    Я на самом деле пытаюсь найти эти две функции (isKindOf: и isMemberOf) Спасибо!
4

Почему бы не использовать встроенные функции, созданные специально для этой задачи?

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

Result: "Array<Any>"
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
}

в Swift 3.

2

Если вы просто хотите проверить класс, не получая предупреждение из-за неиспользуемого определенного значения (пусть someVariable...), вы можете просто заменить материал let булевым:

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

Xcode предложил это, когда я использовал путь let и не использовал определенное значение.

1

Swift 3:

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

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

myObject as? String возвращает nil, если myObject не является String. В противном случае он возвращает String?, поэтому вы можете получить доступ к самой строке с помощью myObject! или добавить ее с помощью myObject! as String безопасно.

0

Если вы не знаете, что в ответе от сервера вы получите массив словарей или отдельный словарь, вам нужно проверить, содержит ли результат массив или нет.
В моем случае всегда получаю массив словарей, кроме одного раза. Итак, чтобы справиться с этим, я использовал приведенный ниже код для Swift 3.

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

Вот как? Array проверяет, является ли полученное значение массивом (элементов словаря). В противном случае вы можете обработать, если это единственный элемент словаря, который не хранится внутри массива.

-1

Если у вас есть ответ вроде этого:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню