Swift 3.1
NSInvocation
可以动态使用,但只是为了锻炼而已,绝不适用于严肃的应用程序。有更好的替代方案。
import Foundation
class Test: NSObject {
@objc var name: String? {
didSet {
NSLog("didSetCalled")
}
}
func invocationTest() {
let namePropertySetterSelector = #selector(setter:name)
let nsInvocationClass: AnyClass = NSClassFromString("NSInvocation")!
let nsInvocationInitializer = unsafeBitCast(
method_getImplementation(
class_getClassMethod(nsInvocationClass, NSSelectorFromString("invocationWithMethodSignature:"))!
),
to: (@convention(c) (AnyClass?, Selector, Any?) -> Any).self
)
let nsInvocationSetSelector = unsafeBitCast(
class_getMethodImplementation(nsInvocationClass, NSSelectorFromString("setSelector:")),
to:(@convention(c) (Any, Selector, Selector) -> Void).self
)
let nsInvocationSetArgAtIndex = unsafeBitCast(
class_getMethodImplementation(nsInvocationClass, NSSelectorFromString("setArgument:atIndex:")),
to:(@convention(c)(Any, Selector, OpaquePointer, NSInteger) -> Void).self
)
let methodSignatureForSelector = NSSelectorFromString("methodSignatureForSelector:")
let getMethodSigniatureForSelector = unsafeBitCast(
method(for: methodSignatureForSelector)!,
to: (@convention(c) (Any?, Selector, Selector) -> Any).self
)
let namyPropertyMethodSigniature = getMethodSigniatureForSelector(self, methodSignatureForSelector, namePropertySetterSelector)
let invocation = nsInvocationInitializer(
nsInvocationClass,
NSSelectorFromString("invocationWithMethodSignature:"),
namyPropertyMethodSigniature
) as! NSObject
nsInvocationSetSelector(
invocation,
NSSelectorFromString("setSelector:"),
namePropertySetterSelector
)
var localName = "New name" as NSString
withUnsafePointer(to: &localName) { stringPointer in
nsInvocationSetArgAtIndex(
invocation,
NSSelectorFromString("setArgument:atIndex:"),
OpaquePointer(stringPointer),
2
)
}
invocation.perform(NSSelectorFromString("invokeWithTarget:"), with: self)
}
}
let object = Test()
object.invocationTest()
NSInvocation
,甚至不应该在Objective-C中使用它。一个可能的解决方案是在字典中使用命名闭包,但即使如此也有点“代码异味”。 - Sulthan#selector
语法部分解决了选择器的问题,但是对于NSInvocation
没有这样的语法。闭包更加安全。由于 Obj-C 中方法的名称会影响内存管理等其他方面,因此还有一些相关方面需要考虑。总之,这是旧的做法,我们现在有更好、更安全的替代方案。 - Sulthan