【问题标题】:Swizzling in Swift with StaticString使用 StaticString 在 Swift 中调动
【发布时间】:2015-11-17 00:20:10
【问题描述】:

我正在尝试调配一个包含 StaticString 参数的 Swift 函数。

这是我尝试过的:

let method = class_getClassMethod(self, original1)

class ABC {
  public static func updateABC(context: Int, str: StaticString) {
  }
}

但是,这不起作用,如果我将 str 的类型更改为 String,我们可以正常 swizzle,任何人有机会使用 StaticString 类型参数来swizzle 函数可以帮忙吗?

谢谢

【问题讨论】:

  • 为什么要这样做?
  • 例如 - Swizzle swift 的 assertFailure @BryanChen
  • 所以下一个问题是......为什么你需要调配assertFailure?你不能只有一个方法myAssertFailure 而是调用它吗?方法 swizzle 是 ObjC 独有的,我认为你不应该将它用于 Swift 项目,因为它不会总是按你预期的那样工作。 Swift 编译器可能会进行激进的内联,这将选择原始实现而不是混合后的实现。
  • 我同意@BryanChen。 Swift 是安全的,即使在 Swift 2 中,反射功能也是只读的(它们应该是只读的)。使用 obj-c 运行时在 Swift 中进行任何形式的 swizzling 是个坏主意;并非每种类型都支持它(原生 swift 类型,如结构、枚举等)
  • 我本人来自 Objective-C,但我仍然发现编写 Swift 代码需要转变思考如何设计类、结构等。虽然有一些情况需要进行动态自省,有很多充分的理由不这样做。我什至会说,可以在 Objective-C 中完成的所有事情都可以在 Swift 中完成,这只是你如何设计类的问题。以 ReactiveCocoa 为例,它主要依靠 KVO 来观察 Swift 所没有的变化。现在他们有了一个新的机制,可变和不可变的属性包装器。

标签: ios swift method-swizzling


【解决方案1】:

StaticString 是一种值类型,因此它没有 Objective-C 表示。因此,它——以及你在其中使用它的声明——不会暴露给 Objective-C 代码或注册到 Objective-C 运行时。另一方面,String 与 Objective-C 兼容(它桥接到 NSString),因此声明与 Objective-C 兼容。

如果你要调配一个方法,你需要用dynamic 标记它,让编译器知道它应该始终通过Objective-C 运行时路由调用,即使在优化代码中也是如此。如果您的函数与 Objective-C 不兼容,使用 dynamic 标记函数也会导致编译器发出错误,这可以帮助您诊断问题。

【讨论】:

  • 谢谢!这是有道理的。因此,当您说声明未在 objc 运行时注册时,该函数如何工作,例如 C++ vTable 查找? Swift/Objc 方法没有绑定到 objc 运行时的任何其他情况?
  • @OliverHu 好问题。 Swift 方法分派有几种不同的方式,由编译器/优化器决定(除非你使用dynamic)。例如在某些情况下它就像一个 vtable,在其他情况下优化器可能会直接内联方法的实现。所有 swift 结构和枚举都使用静态调度。对于纯 swift 类——不从任何 Objective-C 类继承的 Swift 类——编译器也可以选择不在 Objective-C 运行时注册该类。
猜你喜欢
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多