Tôi có một mảng được tạo thành AnyObject
. Tôi muốn lặp lại nó và tìm tất cả các phần tử là các thể hiện mảng.
Làm cách nào để kiểm tra xem một đối tượng có thuộc loại đã cho trong Swift không?
Tôi có một mảng được tạo thành AnyObject
. Tôi muốn lặp lại nó và tìm tất cả các phần tử là các thể hiện mảng.
Làm cách nào để kiểm tra xem một đối tượng có thuộc loại đã cho trong Swift không?
Câu trả lời:
Nếu bạn muốn kiểm tra một loại cụ thể, bạn có thể làm như sau:
if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}
Bạn có thể sử dụng "như!" và điều đó sẽ gây ra lỗi thời gian chạy nếu obj
không phải là kiểu[String]
let stringArray = obj as! [String]
Bạn cũng có thể kiểm tra một yếu tố tại một thời điểm:
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
}
}
?
không có. Nghe có vẻ như as
và ?
khi kết hợp sẽ thực hiện kiểm tra thời gian chạy. Khi nào sẽ thích hợp để sử dụng as
mà không cần ?
? Cảm ơn trước.
as
mà ?
không có cách nào để chương trình của bạn có thể phục hồi từ đối tượng không thuộc loại đó vì chương trình sẽ dừng ngay lập tức nếu không. Sử dụng ?
trong if
câu lệnh cho phép chương trình tiếp tục.
?
trong trường hợp này sẽ thực hiện kiểm tra loại "chung", nếu có, với mệnh đề if, nếu không, cho mệnh đề khác. Nếu không có cái ?
khác sẽ không bao giờ được nhập và như bạn đã chỉ ra gây ra lỗi thời gian chạy. Cảm ơn một lần nữa.
?
cho phép gán trở lại nil
làm cho câu lệnh if trở lại false
và do đó rơi vào câu lệnh khác. Tuy nhiên, tôi nghĩ rằng lời giải thích đó giúp ích cho sự hiểu biết, nhưng if let
thực sự là một trường hợp đặc biệt trong trình biên dịch
Trong Swift 2.2 - 5 bây giờ bạn có thể làm:
if object is String
{
}
Sau đó, để lọc mảng của bạn:
let filteredArray = originalArray.filter({ $0 is Array })
Nếu bạn có nhiều loại để kiểm tra:
switch object
{
case is String:
...
case is OtherClass:
...
default:
...
}
object
như String
bên trong niềng răng (ít nhất là trong Swift 2), trong khi với let
giải pháp bạn có thể thực hiện.
object
trong khối là tốt.
object.uppercaseString
vì kiểu của biến không được đúc để loại đó, bạn chỉ cần kiểm tra rằng đối tượng (được trỏ bởi biến) là mộtString
Nếu bạn chỉ muốn biết nếu một đối tượng là một kiểu con của một kiểu nhất định thì có một cách tiếp cận đơn giản hơn:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
func area (shape: Shape) -> Double {
if shape is Circle { ... }
else if shape is Rectangle { ... }
}
Sử dụng toán tử kiểm tra loại (is) để kiểm tra xem một thể hiện có thuộc loại lớp con nhất định không. Toán tử kiểm tra kiểu trả về true nếu thể hiện của kiểu lớp con đó và false nếu nó không phải. Trích từ: Apple Inc., Ngôn ngữ lập trình Swift. Sách điện tử .
Ở trên, cụm từ 'của một loại lớp con nhất định' rất quan trọng. Việc sử dụngis Circle
và is Rectangle
được trình biên dịch chấp nhận vì giá trị đó shape
được khai báo là Shape
(một siêu lớp của Circle
và Rectangle
).
Nếu bạn đang sử dụng các kiểu nguyên thủy, thì siêu lớp sẽ là Any
. Đây là một ví dụ:
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
vẫn sẽ hoạt động ở đây? Cảm ơn.
object
như Any
. Cập nhật với một ví dụ.
AnyObject
được đề xuất, dường như đã bị vặn lại do AnyObject
không được thừa kế từ NSObject
. Nếu Any
khác, thì đây thực tế cũng là một giải pháp tuyệt vời. Cảm ơn.
Tôi có 2 cách để làm điều đó:
if let thisShape = aShape as? Square
Hoặc là:
aShape.isKindOfClass(Square)
Dưới đây là một ví dụ chi tiết:
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")
}
Chỉnh sửa: 3 ngay bây giờ:
let myShape = Shape()
if myShape is Shape {
print("yes it is")
}
isKindOfClass
là một phương thức của NSObject
giao thức; nó chỉ nên hoạt động cho các lớp chấp nhận nó (tất cả các lớp giảm dần từ NSObject, cộng với bất kỳ lớp Swift tùy chỉnh nào chấp nhận nó một cách rõ ràng)
cho swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Giả sử drawTrigin là một phiên bản của UIView. Để kiểm tra xem drawTrigin có thuộc loại UITableView không:
Trong Swift 3 ,
if drawTriangle is UITableView{
// in deed drawTriangle is UIView
// do something here...
} else{
// do something here...
}
Điều này cũng có thể được sử dụng cho các lớp được xác định bởi chính bạn. Bạn có thể sử dụng điều này để kiểm tra các lượt xem của một khung nhìn.
Tại sao không sử dụng chức năng tích hợp được xây dựng đặc biệt cho nhiệm vụ này?
let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)
Result: "Array<Any>"
Được cảnh báo về điều này:
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)
Tất cả bốn dòng cuối cùng trả về đúng, điều này là do nếu bạn nhập
var r1:CGRect = CGRect()
print(r1 is String)
... Tất nhiên, nó in "sai", nhưng Cảnh báo nói rằng Truyền từ CGRect sang String không thành công. Vì vậy, một số loại được bắc cầu, từ khóa 'là' gọi một từ ẩn.
Bạn nên sử dụng một trong những điều sau đây:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Nếu bạn chỉ muốn kiểm tra lớp mà không nhận được cảnh báo vì giá trị được xác định không sử dụng (hãy để someVariable ...), bạn có thể chỉ cần thay thế công cụ let bằng boolean:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode đã đề xuất điều này khi tôi sử dụng cách cho phép và không sử dụng giá trị được xác định.
Tại sao không sử dụng một cái gì đó như thế này
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
}
trong Swift 3.
Swift 4.2, Trong trường hợp của tôi, sử dụng hàm isKind.
isKind (of :) Trả về giá trị Boolean cho biết người nhận là một thể hiện của lớp đã cho hay một thể hiện của bất kỳ lớp nào kế thừa từ lớp đó.
let items : [AnyObject] = ["A", "B" , ... ]
for obj in items {
if(obj.isKind(of: NSString.self)){
print("String")
}
}
Đọc thêm https://developer.apple.com/documentation/objectivec/nsobjectprotatio/1418511-iskind
Chỉ vì mục đích hoàn chỉnh dựa trên câu trả lời được chấp nhận và một số câu hỏi khác:
let items : [Any] = ["Hello", "World", 1]
for obj in items where obj is String {
// obj is a String. Do something with str
}
Nhưng bạn cũng có thể ( compactMap
cũng "ánh xạ" các giá trị filter
không):
items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }
Và một phiên bản sử dụng 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
}
}
Nhưng bám vào câu hỏi, để kiểm tra xem đó có phải là một mảng không (ví dụ [String]
):
let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]
for obj in items {
if let stringArray = obj as? [String] {
print("\(stringArray)")
}
}
Hoặc nói chung hơn (xem câu trả lời câu hỏi khác này ):
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?
sẽ không luôn cung cấp cho bạn kết quả mong đợi vì as
không kiểm tra xem loại dữ liệu có thuộc loại cụ thể không nhưng chỉ khi loại dữ liệu có thể được chuyển đổi thành hoặc được biểu thị dưới dạng dạng loại cụ thể.
Hãy xem xét mã này chẳng hạn:
func handleError ( error: Error ) {
if let nsError = error as? NSError {
Mỗi loại dữ liệu phù hợp với Error
giao thức có thể được chuyển đổi thành một NSError
đối tượng, vì vậy điều này sẽ luôn thành công . Tuy nhiên, điều đó không có nghĩa error
là trên thực tế đó là một NSError
đối tượng hoặc một lớp con của nó.
Kiểm tra loại chính xác sẽ là:
func handleError ( error: Error ) {
if type(of: error) == NSError.self {
Tuy nhiên, điều này chỉ kiểm tra loại chính xác. Nếu bạn cũng muốn bao gồm lớp con của NSError
, bạn nên sử dụng:
func handleError ( error: Error ) {
if error is NSError.Type {
Nếu bạn có Phản hồi như thế này:
{
"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
}
và bạn muốn kiểm tra giá trị is_stucked
sẽ được đọc là AnyObject, tất cả những gì bạn phải làm là điều này
if let isStucked = response["is_stucked"] as? Bool{
if isStucked{
print("is Stucked")
}
else{
print("Not Stucked")
}
}
Nếu bạn không biết rằng bạn sẽ nhận được một mảng từ điển hoặc từ điển duy nhất trong phản hồi từ máy chủ, bạn cần kiểm tra xem kết quả có chứa một mảng hay không.
Trong trường hợp của tôi luôn nhận được một loạt từ điển ngoại trừ một lần. Vì vậy, để xử lý việc tôi đã sử dụng đoạn mã dưới đây cho swift 3.
if let str = strDict["item"] as? Array<Any>
Đây là? Mảng kiểm tra xem giá trị thu được có phải là mảng không (của các mục trong từ điển). Trong trường hợp khác, bạn có thể xử lý nếu đó là mục từ điển duy nhất không được giữ trong một mảng.
Phiên bản Swift 5.2 & Xcode: 11.3.1 (11C504)
Đây là giải pháp kiểm tra loại dữ liệu của tôi:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
Tôi hy vọng nó sẽ giúp bạn.