Swift类是否有类似isa指针的东西可以重新映射?
我们已经看到Swift uses a more static method dispatch而不是Objective-C(除非来自Foundation / NSObject的类设备)在运行时基于重映射方法实现阻止了混合风格。
我想知道我们将如何实现基于方法拦截的动态功能,如观察者模式,通知等?目前所有这些东西都是由Objective-C层提供的,可以很容易地集成到Swift中。但是,如果我们想在我们自己的框架(或应用程序)中提供这些类型的功能,是否有必要在Objective-C中实现它们?我认为有一种方法可以做到这一点'本地'。
另一种常见于Objective-C的混合是重新映射isa指针以动态生成子类。 Swift是否支持这种调配?如果不是 是 支持拦截任意方法调用的方式?
编辑: 正如@jatoben所指出的,从arm64开始重新映射必须通过调用object_setClass()而不是直接访问该值来完成。这仍然被称为“指针调整'
答案 0 :(得分:11)
看起来方法交换和isa指针重新映射技术只有在Swift类将NSObject作为超类(直接或更高版本)时才有效。当Swift类没有超类或其他非基础类时,它当前不起作用。
以下测试显示:
上课:Birdy
class Birdy: NSObject {
func sayHello()
{
println("tweet tweet")
}
}
上课:HodorBirdy
class HodorBirdy: Birdy {
override func sayHello()
{
super.sayHello()
println("hodor hodor")
}
}
<强>测试强>
func testExample() {
var birdy : Birdy = Birdy()
object_setClass(birdy, HodorBirdy.self)
birdy.sayHello();
}
输出结果符合预期:
tweet tweet
hodor hodor
在此测试中,基类和子类都是事先创建的。虽然它们也可以使用Objective-C运行时动态创建,只要该类具有NSObject作为祖先。
当一个Swift类没有从Objective-C基础派生时,编译器将支持基于静态或基于vtable的调度,因此在这种情况下,它不清楚方法拦截将如何工作!
除非语言/编译器对其作出特定的限制,否则我们将在动态上支持性能。 (拦截,这是动态行为的基础,可以在编译时或运行时完成。对于没有虚拟机的静态或vtable-dispatch,只有编译时适用)。
答案 1 :(得分:2)
我无法回答你关于swift&#34; isa&#34;的问题。相当于,但我想我知道你的基本问题的部分答案。
Property Observers 似乎是Observer Pattern的内置方法。而不是运行时发现&#34;类型&#34; (RTTI,有什么你)它是明确编织的。
来自&#39; Swift编程语言&#39;第345页:
财产观察员观察并回应财产的变化 值。每当物业的价值出现时,都会调用物业观察员 设置,即使新值与属性的当前值相同 值。
您可以将属性观察者添加到您定义的任何存储属性中, 除了懒惰的存储属性。您还可以添加属性观察器 通过覆盖任何继承的属性(无论是存储还是计算) 子类中的属性。
您可以选择在a上定义其中一个或两个观察者 属性:
- 将在存储值之前调用willSet。
存储新值后立即调用- didSet。
我不确定这一切是如何解决的,但我很感兴趣。
依赖于运行时类型发现似乎也与强静态类型正统相反。