写的有点乱
// 为了好测试 只对UIResponder做了延展 讲道理应该给NSobject 做延展
extension UIResponder {
// 消息转发
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
// selectorStr 为方法名字
let selectorStr: String = NSStringFromSelector(aSelector)
// 只检测 UIResponder 的子类 其余暂不检测
if self.isKind(of: NSClassFromString("UIResponder")!) {
// 创建一个虚拟类 RXSwiftTestNew 为项目名字 MyClass 为类名字
let newClass = objc_allocateClassPair(NSObject.classForCoder(), "RXSwiftTestNew.MyClass", 0)
// 为 newClass 添加 ; 一个方法 名字 为 selectorStr ;实现方式为 dosome 所对应的imp指针; v 代表无返回值 ,由于没写 @: 说明无参。这里有个坑,如果用默认的 会默认两个参数。
class_addMethod(newClass, aSelector,dosome(aSelector: aSelector), UnsafeMutablePointer(mutating: "v"))
//注册这个类
objc_registerClassPair(newClass)
// 返回 newClass 的实例 让这个方法的实现转发到 newClass
let Protector: AnyClass? = newClass.self
let instance: Any? = Protector
// 下面是做个测试 获取新建虚拟类的方法列表
var methodCount:UInt32 = 0
let methodList = class_copyMethodList(Protector.self, &methodCount)
for i in 0..
let temp = methodList?[Int(i)]
var imp = method_getImplementation(temp)
var name_f = method_getName(temp)
let name_s = sel_getName(method_getName(temp))
var arguments = method_getNumberOfArguments(temp)
let encoding = method_getTypeEncoding(temp)
print("方法名:\(NSString(utf8String: name_s!)),参数个数:\(arguments),编码方式\(NSString(utf8String: encoding!)))")
}
// 实验结束
// 比较惆怅的是 方法已经添加上了 但是无法响应
return instance!
}else{
return nil
}
}
func dosome(aSelector:Selector)->IMP?{
let block = {()->() in
// 预计 闪退就会走这里
print("没有闪退" + NSStringFromSelector(aSelector))
}
// 这里也是个坑 这种操作是不安全的 所以Swift 要求我们必须这么包装一层 否则若直接使用block无法编译!!!!
let castedBlock: AnyObject = unsafeBitCast(block as @convention(block) () -> Void, to: AnyObject.self)
let swizzledImplementation = imp_implementationWithBlock(castedBlock)
// 返回 block 对应的方法指针
return swizzledImplementation
}
}
ps: 为什么我已经在类用class_addMethod添加了这个方法,但是却无法用performSelector调用呢? 求大神解答
感谢 @Mad_Mark @网易大白