しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

【Swift】isとisMemberOfClassとisKindOfClass

isとisMemberOfClassとisKindOfClassですが、挙動の差がわかりにくかったのでまとめてみました。

isKindOfClass

下のようなケースでは当然trueになります。
それとisKindOfClass/isMemberOfClassはNSObjectProtocolのメソッドなので、NSObjectなどを継承しているクラスでのみ使えます。

class MyClass: NSObject {}

let myClass = MyClass()
print(myClass.isKind(of: MyClass.self)) // → true

isKindOfClassは判定対象が引数のサブクラスの場合もtrueになります。

class MyClass: NSObject {}
class MySubClass: MyClass {}

let myClass = MySubClass()
print(myClass.isKind(of: MyClass.self)) // → true

isMemberOfClass

isMemberOfClassはisKindOfClassと違って、サブクラスとの判定はfalseになります。

class MyClass: NSObject {}
class MySubClass: MyClass {}

print(MyClass().isKind(of: MyClass.self)) // → true
print(MySubClass().isKind(of: MyClass.self)) // → false

is

isはisKindOfClass同様、サブクラスとの判定もtrueになります。
isKindOfClassと違い、NSObjectProtocolに準拠していないクラスでも使えます。

class MyClass {}
class MySubClass: MyClass {}

print(MyClass() is MyClass) // → true
print(MySubClass() is MyClass) // → true

isMemberOfClass相当の判定方法

NSObjectProtocolに準拠してないクラスでisMemberOfClass同様の判定をしたい場合は、下の方法が使えそうです。
String(describing: type(of: myClass))と"(MyClass.self)"はクラス名を返すので、サブクラスとの比較がfalseになります。

class MyClass {}
class MySubClass: MyClass {}

let myClass = MyClass()
let mySubClass = MySubClass()
print(String(describing: type(of: myClass)) == "\(MyClass.self)")
print(String(describing: type(of: mySubClass)) == "\(MyClass.self)")

文字列での判定なので、下のように別フレームワークと同じクラス名を使ってる場合は注意が必要です。

class UIView {}

print(UIView() is UIKit.UIView) // → false
print(String(describing: type(of: UIView())) == "\(UIKit.UIView.self)") → true