我需要检查一个对象的类是否有一个可用于赋值的成员。我们假设有一个班级:
class MyClass: NSObject {
var myVar : AnyObject!
// ...
}
我尝试了这种objC风格,但属性在Swift中是一个不同的野兽,第二行总是返回false:
let myClass: MyClass = MyClass()
let hasClassMember = myClass.respondsToSelector(Selector("setMyVar:"))
if hasClassMember {
myClass.performSelector("setMyVar:", withObject: "Context" as! AnyObject)
}
我认为Swift没有像ObjC那样强大的反射,但有没有解决方案?
UPDATE 事实证明我的代码有效,但我已将其简化为演示目的。奇怪的是,一旦我将myVar的类型更改为某个自定义类的实例,respontsToSelector就会停止工作,比方说ClassB。感觉有点神奇...... :)
UPDATE2 最后我发现了问题。我还没有编写完整的代码,认为问题出在其他地方,无论如何,这里是完整的代码。 MyClass变量实际上是一个实现AnotherClassProtocol
的其他AnotherClass的类型protocol AnotherClassProtocol {
//…
}
class AnotherClass: AnotherClassProtocol {
//…
}
class MyClass: NSObject {
var myVar : AnotherClass!
// ...
}
这导致myClass.respondsToSelector(Selector(“setMyVar:”))总是返回false。原来问题是因为我在AnotherClass声明中省略了NSObject的扩展。在我修复了它之后,它开始按预期工作:
class AnotherClass: NSObject, AnotherClassProtocol {
//…
}
我还在学习Swift并且认为不需要NSObject,因为编译器没有抱怨并且无论如何都从NSObject扩展(至少在ObjC中)。好吧,我很高兴我发现了这个讨厌的错误。
答案 0 :(得分:7)
比检查选择器稍微好一点的方法就是使用协议。
protocol MyClassProtocol {
var myVar : AnyObject! {get set}
}
class MyClass: NSObject, MyClassProtocol {
var myVar : AnyObject!
// ...
}
...
let c = MyClass()
if let conformingMyClass = c as? MyClassProtocol { // returns true
print("yay")
conformingMyClass.myVar = "Context"
} else {
print("nay")
}
通过这种方式,可以更清楚地了解哪些课程有并且没有你的财产,而且你不必与选择者混淆(更多的是Swift-y)。
答案 1 :(得分:5)
import Foundation
class MyClass: NSObject {
var myVar1 : AnyObject!
// ...
}
let myClass: MyClass = MyClass()
let hasClassMemberMyVar1 = myClass.respondsToSelector(Selector("setMyVar1:")) // true
let hasClassMemberMyVar2 = myClass.respondsToSelector(Selector("setMyVar2:")) // false
它对我有用......
更新,基于OP备注
import Foundation
class C:NSObject {}
class MyClass: NSObject {
var myVar1 : C? // Objective-C representable
var i: Int = 0 // Objective-C representable
var j: Int? = 10
}
let myClass: MyClass = MyClass()
let hasClassMemberMyVar1 = myClass.respondsToSelector(Selector("setMyVar1:")) // true
let hasClassMemberMyVar2 = myClass.respondsToSelector(Selector("setMyVar2:")) // false
let hasClassMemberI = myClass.respondsToSelector(Selector("setI:")) // true
let hasClassMemberJ = myClass.respondsToSelector(Selector("setJ:")) // false, because Optional<Int> is not representable in Objective-C !!!
print(myClass.i.dynamicType, myClass.j.dynamicType) // Int Optional<Int>
仅限类型属性
import Foundation
class C:NSObject {}
class C1 {}
class MyClass: NSObject {
var c : C?
var cO1: C = C()
var cO2: C!
var c1: C1 = C1()
var c2: C1?
var c3: C1!
}
let myClass: MyClass = MyClass()
let hasClassMemberC = myClass.respondsToSelector(Selector("setC:")) // true
let hasClassMemberCO1 = myClass.respondsToSelector(Selector("setCO1:")) // true
let hasClassMemberCO2 = myClass.respondsToSelector(Selector("setCO2:")) // true
let hasClassMemberC1 = myClass.respondsToSelector(Selector("setC1:")) // false, class C1 is not Objective-C representable ...
let hasClassMemberC2 = myClass.respondsToSelector(Selector("setC2:")) // false, Optional<C1> is not Objective-C representable ...
let hasClassMemberC3 = myClass.respondsToSelector(Selector("setC3:")) // false, ImplicitlyUnwrappedOptional<C1> is not Objective-C representable ...
答案 2 :(得分:3)
Swift 3版Ryan Huubert的回答:
class MyClass: NSObject {
var myVar : AnyObject!
// ...
}
let myClass = MyClass()
myClass.responds(to: Selector("myVar")) // returns true
myClass.responds(to: Selector("myVar:")) // returns false
答案 3 :(得分:1)
class MyClass: NSObject {
var myVar : AnyObject!
// ...
}
let myClass = MyClass()
myClass.respondsToSelector("myVar") // returns true
myClass.respondsToSelector("myVar:") // returns false