У меня есть массив, который состоит из 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, если ваша программа не сможет восстановить объект, не относящийся к этому типу, потому что программа немедленно остановится, если это не так. Использование оператора ?
in if
позволяет программе продолжить.
?
в этом случае будет выполнять «общую» проверку типа, если да, для предложения if, если нет - для предложения else. Без этого ?
никогда не будет введено и, как вы указали, вызвать ошибку во время выполнения. Еще раз спасибо.
?
позволяет возвращать присваивание, nil
вызывая возврат оператора if false
и, следовательно, переходя к оператору else. Тем не менее, я думаю, что объяснение помогает с пониманием, но 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 { ... }
}
«Используйте оператор проверки типа (is), чтобы проверить, принадлежит ли экземпляр определенному типу подкласса. Оператор проверки типа возвращает true, если экземпляр принадлежит к этому типу подкласса, и false, если это не так ». Выдержка из: Apple Inc. «Язык программирования Swift». интерактивные книги .
В вышесказанном важна фраза «определенного типа подкласса». Использование 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
все по-другому, то это было бы действительно отличным решением. Спасибо.
У меня есть 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")
}
isKindOfClass
это метод NSObject
протокола; он должен работать только для классов, которые его принимают (все классы, происходящие из NSObject, плюс любой пользовательский класс Swift, который принимает его явно)
для swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Предположим, что drawTriangle является экземпляром UIView.To проверить, имеет ли 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)
Все четыре последние строки возвращают true, потому что если вы наберете
var r1:CGRect = CGRect()
print(r1 is String)
... он печатает "ложь", конечно, но Предупреждение говорит о том, что приведение из CGRect к String завершается неудачно. Таким образом, некоторые типы являются мостовыми, а ключевое слово is вызывает неявное приведение.
Вы должны лучше использовать один из них:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Если вы просто хотите проверить класс без предупреждения из-за неиспользуемого определенного значения (let someVariable ...), вы можете просто заменить let let на логическое значение:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode предложил это, когда я использовал let way и не использовал определенное значение.
Почему бы не использовать что-то подобное
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.
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")
}
}
Если вы не знаете, что в ответе от сервера вы получите массив словарей или отдельный словарь, вам нужно проверить, содержит ли результат массив или нет.
В моем случае всегда получаю массив словарей, кроме одного раза. Итак, чтобы справиться с этим, я использовал приведенный ниже код для Swift 3.
if let str = strDict["item"] as? Array<Any>
Вот как? Array проверяет, является ли полученное значение массивом (из словарных элементов). В противном случае вы можете обработать, если это единственный элемент словаря, который не хранится внутри массива.
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.")
}
Я надеюсь, что это поможет вам.