如何使用 perform(#selector(setter:)) 使用 swift 4 设置 属性 的值?
How do you use perform(#selector(setter:)) to set the value of a property using swift 4?
我正在尝试 运行 这段代码,但它产生了意想不到的结果。
class Test: NSObject {
@objc var property: Int = 0
}
var t = Test()
t.perform(#selector(setter: Test.property), with: 100)
print(t.property)
正在打印的值是一些垃圾数字-5764607523034233277
。如何使用 perform 方法设置 属性 的值?
performSelector:withObject:
方法需要一个对象参数,因此 Swift 将基本类型 100 转换为对象引用。
setProperty:
方法(#selector(setter: Test.property)
的计算结果)采用原始 NSInteger
参数。所以它将对象引用视为整数。
由于这种不匹配,您无法以有意义的方式使用 performSelector:withObject:
调用 setProperty:
。
但是,您可以改用 setValue:forKey:
和 #keyPath
,因为 Key-Value 编码知道如何将对象转换为基元:
t.setValue(100, forKey: #keyPath(Test.property))
您不能使用 perform(_:with:)
来执行此操作,因为 Int
不是 arg 所必需的 NSObject
子类。要指定类型,您可以使用以下解决方法:
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)
您可以在我的回答中找到更多详细信息和示例here
我正在尝试 运行 这段代码,但它产生了意想不到的结果。
class Test: NSObject {
@objc var property: Int = 0
}
var t = Test()
t.perform(#selector(setter: Test.property), with: 100)
print(t.property)
正在打印的值是一些垃圾数字-5764607523034233277
。如何使用 perform 方法设置 属性 的值?
performSelector:withObject:
方法需要一个对象参数,因此 Swift 将基本类型 100 转换为对象引用。
setProperty:
方法(#selector(setter: Test.property)
的计算结果)采用原始 NSInteger
参数。所以它将对象引用视为整数。
由于这种不匹配,您无法以有意义的方式使用 performSelector:withObject:
调用 setProperty:
。
但是,您可以改用 setValue:forKey:
和 #keyPath
,因为 Key-Value 编码知道如何将对象转换为基元:
t.setValue(100, forKey: #keyPath(Test.property))
您不能使用 perform(_:with:)
来执行此操作,因为 Int
不是 arg 所必需的 NSObject
子类。要指定类型,您可以使用以下解决方法:
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)
您可以在我的回答中找到更多详细信息和示例here