简体   繁体   English

你如何使用perform(#selector(setter :))来使用swift 4设置属性的值?

[英]How do you use perform(#selector(setter:)) to set the value of a property using swift 4?

I'm trying to run this code but it's yielding unexpected results. 我正在尝试运行此代码,但它会产生意想不到的结果。

class Test: NSObject {
    @objc var property: Int = 0
}

var t = Test()

t.perform(#selector(setter: Test.property), with: 100)
print(t.property)

The value being printed is some junk number -5764607523034233277 . 打印的值是一些垃圾编号-5764607523034233277 How can I set the value of a property using the perform method? 如何使用perform方法设置属性的值?

The performSelector:withObject: method requires an object argument, so Swift is converting the primitive 100 to an object reference. performSelector:withObject:方法需要一个object参数,因此Swift performSelector:withObject:语100转换为一个对象引用。

The setProperty: method (which is what #selector(setter: Test.property) evaluates to) takes a primitive NSInteger argument. setProperty:方法( #selector(setter: Test.property)求值的方法)采用原始NSInteger参数。 So it is treating the object reference as an integer. 所以它将对象引用视为整数。

Because of this mismatch, you cannot invoke setProperty: using performSelector:withObject: in a meaningful way. 由于这种不匹配,您不能以有意义的方式使用performSelector:withObject:来调用setProperty:

You can, however, use setValue:forKey: and a #keyPath instead, because Key-Value Coding knows how to convert objects to primitives: 但是,您可以使用setValue:forKey:#keyPath ,因为键值编码知道如何将对象转换为基元:

t.setValue(100, forKey: #keyPath(Test.property))

You can't use perform(_:with:) to do that since Int is not a NSObject subclass which is necessary for the arg. 你不能使用perform(_:with:)来做到这一点,因为Int不是arg所必需的NSObject子类。 To specify the type you can workaround it with: 要指定类型,您可以使用以下方法解决此问题:

let setterSelector = #selector(setter: Test.property)
let setterIMP = t.method(for: setterSelector)
//Invoking setter
unsafeBitCast(setterIMP,to:(@convention(c)(Any?,Selector,Int)->Void).self)(t, setterSelector,100)

let getterSelector = #selector(getter: Test.property)
let getterIMP = t.method(for: getterSelector)
//Invoking getter
let intValue = unsafeBitCast(getterIMP,to:(@convention(c)(Any?,Selector)->Int).self)(t, getterSelector)

You can find more details and examples in my answer here 你可以在我的答案找到更多细节和例子在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM