Saya memiliki array yang terdiri dari AnyObject
. Saya ingin mengulanginya, dan menemukan semua elemen yang merupakan instance array.
Bagaimana saya bisa memeriksa apakah suatu objek dari tipe tertentu di Swift?
Saya memiliki array yang terdiri dari AnyObject
. Saya ingin mengulanginya, dan menemukan semua elemen yang merupakan instance array.
Bagaimana saya bisa memeriksa apakah suatu objek dari tipe tertentu di Swift?
Jawaban:
Jika Anda ingin memeriksa jenis tertentu, Anda dapat melakukan hal berikut:
if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}
Anda dapat menggunakan "sebagai!" dan itu akan menimbulkan kesalahan runtime jika obj
bukan tipe[String]
let stringArray = obj as! [String]
Anda juga dapat memeriksa satu elemen sekaligus:
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
}
}
?
tidak ada. Kedengarannya seperti as
dan ?
ketika digabungkan akan melakukan pemeriksaan runtime. Kapan akan tepat untuk digunakan as
tanpa ?
? Terima kasih sebelumnya.
as
tanpa ?
jika tidak ada cara program Anda bisa pulih dari objek yang tidak seperti itu karena program akan segera berhenti jika tidak. Menggunakan ?
dalam if
pernyataan memungkinkan program untuk melanjutkan.
?
dalam hal ini akan melakukan pemeriksaan tipe "generik", jika ya, ke klausa if, jika tidak, ke klausa lain. Tanpa yang ?
lain tidak akan pernah dimasukkan dan saat Anda menunjukkan menyebabkan kesalahan runtime. Terima kasih lagi.
?
memungkinkan tugas untuk kembali nil
menyebabkan jika pernyataan untuk kembali false
dan karena itu jatuh melalui pernyataan lain. Namun, saya pikir penjelasan itu membantu dengan pemahaman, tetapi if let
sebenarnya adalah kasus khusus dalam kompiler
Di Swift 2.2 - 5 sekarang Anda dapat melakukan:
if object is String
{
}
Kemudian untuk memfilter array Anda:
let filteredArray = originalArray.filter({ $0 is Array })
Jika Anda memiliki beberapa jenis untuk diperiksa:
switch object
{
case is String:
...
case is OtherClass:
...
default:
...
}
object
sebagai String
di dalam kawat gigi (setidaknya di Swift 2), sedangkan dengan let
solusi Anda bisa melakukannya.
object
di blok tidak masalah.
object.uppercaseString
karena jenis variabel tidak dicor ke jenis itu, Anda hanya memeriksa bahwa objek (ditunjukkan oleh variabel) adalahString
Jika Anda hanya ingin tahu apakah suatu objek merupakan subtipe dari jenis yang diberikan maka ada pendekatan yang lebih sederhana:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
func area (shape: Shape) -> Double {
if shape is Circle { ... }
else if shape is Rectangle { ... }
}
“Gunakan operator pengecekan tipe untuk memeriksa apakah instance dari tipe subclass tertentu. Operator pemeriksa tipe mengembalikan true jika turunannya dari jenis subclass dan false jika tidak. " Kutipan dari: Apple Inc. “Bahasa Pemrograman Swift.” iBooks .
Dalam kalimat di atas frasa 'dari jenis subclass tertentu' adalah penting. Penggunaan is Circle
dan is Rectangle
diterima oleh kompiler karena nilai shape
tersebut dinyatakan sebagaiShape
(superclass dari Circle
dan Rectangle
).
Jika Anda menggunakan tipe primitif, superclass akan menjadi Any
. Berikut ini sebuah contoh:
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
masih akan berfungsi di sini? Terima kasih.
object
sebagai Any
. Diperbarui dengan sebuah contoh.
AnyObject
disarankan, tampaknya telah dibalas karena AnyObject
tidak diwarisi dari NSObject
. Jika Any
berbeda, maka ini sebenarnya akan menjadi solusi yang bagus juga. Terima kasih.
Saya punya 2 cara untuk melakukannya:
if let thisShape = aShape as? Square
Atau:
aShape.isKindOfClass(Square)
Ini adalah contoh terperinci:
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")
}
Edit: 3 sekarang:
let myShape = Shape()
if myShape is Shape {
print("yes it is")
}
isKindOfClass
adalah metode NSObject
protokol; seharusnya hanya berfungsi untuk kelas yang mengadopsinya (semua kelas turun dari NSObject, ditambah kelas Swift khusus yang mengadopsinya secara eksplisit)
untuk swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Asumsikan drawTriangle adalah turunan dari UIView. Untuk memeriksa apakah drawTriangle bertipe UITableView:
Dalam Swift 3 ,
if drawTriangle is UITableView{
// in deed drawTriangle is UIView
// do something here...
} else{
// do something here...
}
Ini juga dapat digunakan untuk kelas yang Anda tentukan sendiri. Anda bisa menggunakan ini untuk memeriksa subview tampilan.
Mengapa tidak menggunakan fungsionalitas bawaan yang dibangun khusus untuk tugas ini?
let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)
Result: "Array<Any>"
Diperingatkan tentang ini:
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)
Semua empat baris terakhir mengembalikan true, ini karena jika Anda mengetik
var r1:CGRect = CGRect()
print(r1 is String)
... itu mencetak "false" tentu saja, tetapi Peringatan mengatakan bahwa Cast dari CGRect ke String gagal. Jadi, beberapa jenis dijembatani, dan kata kunci 'is' memanggil pemeran implisit.
Anda sebaiknya menggunakan salah satu dari ini:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Jika Anda hanya ingin memeriksa kelas tanpa mendapat peringatan karena nilai yang didefinisikan tidak digunakan (biarkan someVariable ...), Anda dapat dengan mudah mengganti barang yang dibiarkan dengan boolean:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode mengusulkan ini ketika saya menggunakan cara membiarkan dan tidak menggunakan nilai yang ditentukan.
Mengapa tidak menggunakan sesuatu seperti ini
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
}
dalam Swift 3.
Swift 4.2, Dalam kasus saya, menggunakan fungsi isKind.
isKind (of :) Mengembalikan nilai Boolean yang menunjukkan apakah penerima adalah turunan dari kelas yang diberikan atau turunan dari kelas apa pun yang mewarisi dari kelas itu.
let items : [AnyObject] = ["A", "B" , ... ]
for obj in items {
if(obj.isKind(of: NSString.self)){
print("String")
}
}
Readmore https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418511-iskind
Hanya demi kelengkapan berdasarkan jawaban yang diterima dan beberapa lainnya:
let items : [Any] = ["Hello", "World", 1]
for obj in items where obj is String {
// obj is a String. Do something with str
}
Tetapi Anda juga bisa ( compactMap
juga "memetakan" nilai-nilai yang filter
tidak):
items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }
Dan versi menggunakan 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
}
}
Tetapi berpegang pada pertanyaan, untuk memeriksa apakah itu array (yaitu [String]
):
let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]
for obj in items {
if let stringArray = obj as? [String] {
print("\(stringArray)")
}
}
Atau lebih umum (lihat jawaban pertanyaan lain ini ):
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?
tidak akan selalu memberikan hasil yang diharapkan karena as
tidak uji apakah tipe data adalah dari jenis tertentu tetapi hanya jika tipe data dapat dikonversi ke atau direpresentasikan sebagai jenis tertentu.
Pertimbangkan kode ini misalnya:
func handleError ( error: Error ) {
if let nsError = error as? NSError {
Setiap tipe data yang sesuai dengan Error
protokol dapat dikonversi ke NSError
objek, jadi ini akan selalu berhasil . Namun itu tidak berarti bahwa error
pada kenyataannya NSError
objek atau subkelas dari itu.
Jenis cek yang benar adalah:
func handleError ( error: Error ) {
if type(of: error) == NSError.self {
Namun, ini hanya memeriksa untuk jenis yang tepat. Jika Anda ingin juga menyertakan subkelas dari NSError
, Anda harus menggunakan:
func handleError ( error: Error ) {
if error is NSError.Type {
Jika Anda Memiliki Respons Seperti Ini:
{
"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
}
dan Anda ingin memeriksa nilai is_stucked
yang akan dibaca sebagai AnyObject, yang harus Anda lakukan adalah ini
if let isStucked = response["is_stucked"] as? Bool{
if isStucked{
print("is Stucked")
}
else{
print("Not Stucked")
}
}
Jika Anda tidak tahu bahwa Anda akan mendapatkan array kamus atau kamus tunggal dalam respons dari server, Anda perlu memeriksa apakah hasilnya berisi array atau tidak.
Dalam kasus saya selalu menerima array kamus kecuali sekali. Jadi, untuk mengatasinya saya menggunakan kode di bawah ini untuk swift 3.
if let str = strDict["item"] as? Array<Any>
Di sini sebagai? Array memeriksa apakah nilai yang diperoleh adalah array (dari item kamus). Dalam kasus lain, Anda dapat menangani jika item kamus tunggal yang tidak disimpan di dalam array.
Versi Swift 5.2 & Xcode: 11.3.1 (11C504)
Inilah solusi saya untuk memeriksa tipe data:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
Saya harap ini akan membantu Anda.