Swift函数调配/运行时

ato*_*nda 20 runtime swizzling swift

在Swift之前,在Objective-C中,我会在类中调用或挂钩方法<objc/runtime.h>.

如果有人有任何关于修改Swift的运行时和挂钩函数的信息,比如CydiaSubstrate和其他帮助这个领域的库,请通知我.

mba*_*liy 36

我在Swift中使用方法调配成功了.此示例显示如何在NSDictionary上挂钩描述方法

我的实施:

extension NSDictionary {
     func myDescription() -> String!{
        println("Description hooked")
        return "Hooooked " + myDescription();
    }
}
Run Code Online (Sandbox Code Playgroud)

调色代码:

func swizzleEmAll() {
        var dict:NSDictionary = ["SuperSecret": kSecValueRef]
        var method: Method = class_getInstanceMethod(object_getClass(dict), Selector.convertFromStringLiteral("description"))

        println(dict.description) // Check original description

        var swizzledMethod: Method = class_getInstanceMethod(object_getClass(dict), Selector.convertFromStringLiteral("myDescription"))
        method_exchangeImplementations(method, swizzledMethod)

        println(dict.description) //Check that swizzling works
    }
Run Code Online (Sandbox Code Playgroud)

编辑: 此代码适用于任何继承自NSObject的自定义Swift类(但不适用于不支持的类.)更多示例 - https://github.com/mbazaliy/MBSwizzler

  • 为了清楚起见,这个例子在Objective-C中定义的类上调用了一个方法,而不是swift.我猜,因为提问者接受了答案,这就是他们想要的,但是对于记录,这种方法不会在纯粹的快速类上调整方法. (19认同)
  • @mbazaliy,在我的测试中,你的`myDescription()`递归调用自身并导致堆栈溢出错误. (3认同)
  • 在“关联对象”之后,有一个使用 Swift 进行 Swizzling 的好例子[此处](http://nshipster.com/swift-objc-runtime/) (2认同)

ipm*_*mcc 19

你很可能会在没有任何问题的情况下调用从Objective-C类继承的swift生成的类,因为它们似乎一直使用动态方法调度.您可以通过跨桥传递在Objective-C运行时中存在的快速定义的类的方法,但Objective-C方法可能只是通过桥接到swift的代理 - 边运行时,所以不清楚它们是否特别有助于调整它们.

"纯粹的"快速方法调用似乎不是通过任何类似的方式动态调度的objc_msgSend,并且看起来(来自简短的实验)swift的类型安全性在编译时实现,并且大部分实际类型信息不存在(即消失)在运行时为非类型类型(这两种类型都可能有助于swift的速度优势.)

出于这些原因,我认为有意义的混合swift-only方法将比调整Objective-C方法更难,并且可能看起来mach_override比Objective-C方法更加混乱.

  • 我非常怀疑使用现有的Objective-C调配方法可以调节静态和vtable调度方法,这有点我试图做的,虽然看起来这不是OP所要求的鉴于他们接受了不同的答案. (3认同)

Umb*_*ndi 5

一年多以后,我正在回答这个问题,因为其他答案都没有提供针对各类课程调整的明确要求.

什么是其他的描述,而它将完美的运作进行功能扩展到基础/ UIKit类(如NSDictionary中),只会永远不会为自己的雨燕类工作.

如上所述这里,有一个方法混写其他比你的自定义类扩展NSObject的一个额外的要求.

必须标记 您想要调配的快速方法dynamic.

如果不对其进行标记,则运行时将继续调用原始方法而不是调整方法,即使方法指针看起来已正确交换.

更新:

在博文中扩展了这个答案.