如何检查对象是否具有存储属性? [英] How to check if an object has a stored property?

查看:55
本文介绍了如何检查对象是否具有存储属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要检查一个对象的类是否有一个可用于赋值的成员.假设有一个类:

I need to check if an object's class has a member which could be used for assigning a value. Let's say there's a class:

class MyClass: NSObject {

  var myVar : AnyObject!

  // ...
}

我尝试了这种 objC 样式,但属性在 Swift 中是一个不同的野兽,第二行总是返回 false:

I tried this objC style but properties are a different beast in Swift and second line always returns false:

let myClass: MyClass = MyClass()
let hasClassMember = myClass.respondsToSelector(Selector("setMyVar:"))

if hasClassMember {

  myClass.performSelector("setMyVar:", withObject: "Context" as! AnyObject)
} 

我认为 Swift 没有 ObjC 那样强大的反射,但是有什么解决方案吗?

I assume Swift doesn't have a powerful reflection as ObjC has, but is there any solution?

更新 事实证明我的代码有效,但是为了演示目的我已经简化了它.奇怪的是,一旦我将 myVar 的类型更改为某个自定义类的实例,例如 ClassB,respondsToSelector 就会停止工作.感觉有点神奇... :)

UPDATE It turns out my code works, however I have simplified it for demo purposes. The weird part is respondsToSelector stops working as soon as I change the type of myVar to be an instance of some custom class, let say ClassB. Feels it a bit magic... :)

UPDATE2 终于找到了问题所在.我没有写完整代码,还以为问题出在别处,反正这里是完整代码.MyClass 变量实际上是其他实现 AnotherClassProtocol 的其他 AnotherClass 的一种类型

UPDATE2 Finally I found the problem. I haven't wrote the full code, thought the problem is elsewhere, anyway, here's the full code. MyClass variable is actually a type of some other AnotherClass which implements AnotherClassProtocol

protocol AnotherClassProtocol {
  //…
}

class AnotherClass: AnotherClassProtocol {
  //…
}

class MyClass: NSObject {

  var myVar : AnotherClass!
  // ...
}

这导致 myClass.respondsToSelector(Selector("setMyVar:")) 总是返回 false.事实证明,问题是因为我在 AnotherClass 声明中省略了对 NSObject 的扩展.在我解决这个问题后,它开始按预期工作:

This was causing myClass.respondsToSelector(Selector("setMyVar:")) always return false. It turns out the problem was because I omitted extending of NSObject in my AnotherClass declaration. It starts working as expected after I fixed that:

class AnotherClass: NSObject, AnotherClassProtocol {
  //…
}

我仍在学习 Swift 并认为不需要 NSObject,因为编译器没有抱怨,而且一切都从 NSObject 扩展而来(至少在 ObjC 中).好吧,我很高兴我发现了这个讨厌的错误.

I'm still learning Swift and thought NSObject is not needed as the compiler was not complaining and everything extend from NSObject anyway (at least in ObjC). Well, I'm glad I found this nasty bug.

推荐答案

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

它对我有用......

it works for me ...

更新,基于 OP 注释

UPDATE, based on OP notes

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 ...

这篇关于如何检查对象是否具有存储属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆