我有一个由组成的数组AnyObject
。我想对其进行迭代,并找到所有属于数组实例的元素。
如何在Swift中检查对象是否为给定类型?
我有一个由组成的数组AnyObject
。我想对其进行迭代,并找到所有属于数组实例的元素。
如何在Swift中检查对象是否为给定类型?
Answers:
如果要检查特定类型,可以执行以下操作:
if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}
您可以使用“ as!” 如果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将对if子句进行“泛型”类型检查,如果不是,则对else子句进行类型检查。如果没有?
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。” 摘录自:苹果公司“ The Swift Programming Language”。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
as 声明为,它应该可以工作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类)
请注意以下事项:
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)
...当然会显示“ false”,但警告消息说从CGRect转换为String失败。因此,某些类型被桥接,ans“ is”关键字称为隐式转换。
您最好使用以下之一:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
如果由于未使用定义的值而只想检查该类而没有警告(请让someVariable ...),则可以简单地将let替换为布尔值:
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")
}
}
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.")
}
希望对您有帮助。