2016-02-14 3 views
2

Мне нужно проверить, имеет ли класс объекта член, который можно использовать для назначения значения. Скажем, есть класс:Как проверить, хранится ли у объекта свойство?

class MyClass: NSObject { 

    var myVar : AnyObject! 

    // ... 
} 

Я попробовал этот стиль ObjC но свойства другой зверь в Swift и вторая линия всегда возвращает ложь:

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

if hasClassMember { 

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

Я предполагаю, что Swift не имеет мощное отражение как ObjC имеет, но есть ли какое-либо решение?

UPDATE Оказалось, что мой код работает, однако я упростил его для демонстрационных целей. Странная часть реагируетToSelector перестает работать, как только я изменяю тип myVar как экземпляр некоторого пользовательского класса, пусть ClassB. Чувствует себя немного волшебным ... :)

UPDATE2 И, наконец, я нашел проблему. Я не написал полный код, думал, что проблема в другом месте, так или иначе, вот полный код. переменная MyClass фактически является типом некоторой другой AnotherClass, который реализует AnotherClassProtocol

protocol AnotherClassProtocol { 
    //… 
} 

class AnotherClass: AnotherClassProtocol { 
    //… 
} 

class MyClass: NSObject { 

    var myVar : AnotherClass! 
    // ... 
} 

Это вызывает myClass.respondsToSelector (Selector ("setMyVar:")) всегда возвращает ложь. Оказывается, проблема была в том, что я пропустил расширение NSObject в своей декларации AnotherClass. Он начинает работать, как ожидается, после того, как я установил, что:

class AnotherClass: NSObject, AnotherClassProtocol { 
    //… 
} 

Я все еще учусь Свифт и подумал NSObject не нужен, поскольку компилятор не жаловался и все простираются от NSObject в любом случае (по крайней мере, в ObjC). Ну, я рад, что нашел эту неприятную ошибку.

+0

Я попробовал этот код на детской площадке, и он работал правильно для меня. Я должен был удалить это! AnyObject и я также удаляю 'selector()' вокруг 'setMyVar:', поскольку он не нужен. 'hasClassMember' также был true/false на основе имени свойства – Paulw11

ответ

3
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 

это работает для меня ...

UPDATE, на основе ОП отмечает

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

Похоже, что он работает с myVar, являющимся типом AnyObject, однако это не так, если бы я изменил его тип. Проверьте мое обновление. – Centurion

+0

@Centurion, если тип myVar1 наследуется от NSObject, он все равно должен работать.Примите во внимание, что Селектор работает только для динамического связывания, поэтому ваше свойство класса должно быть также Objective-C. – user3441734

+0

@Centurion i добавил пример, где все свойства - некоторый класс (ссылочный тип) – user3441734

1
class MyClass: NSObject { 

    var myVar : AnyObject! 
    // ... 
} 

let myClass = MyClass() 

myClass.respondsToSelector("myVar") // returns true 
myClass.respondsToSelector("myVar:") // returns false 
+0

Пожалуйста, проверьте вопрос об обновлении – Centurion

3

немного лучше чем проверка на sele ctors будет использовать протокол.

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

2

Swift 3 вариант ответа Райан Huubert в:

class MyClass: NSObject { 

    var myVar : AnyObject! 
    // ... 
} 

let myClass = MyClass() 

myClass.responds(to: Selector("myVar")) // returns true 
myClass.responds(to: Selector("myVar:")) // returns false 
Смежные вопросы