为什么我不能在协议中声明动态变量

时间:2019-01-09 20:24:21

标签: swift dynamic swift-protocols

我目前正在为我的对象开发协议,该协议继承自Realm的Object。在我的对象中,我有变量,这些变量被标记为@objc dynamic

@objc dynamic var title: String = ""

现在想象一下,我有更多具有相同变量title的相似对象。我想为他们创建协议,因为我只想有一种通用的方法来更改对象的标题。

因此,我创建了带有标记为title的{​​{1}}变量的协议,期望它是这样工作的

@objc dynamic

...这没有解决,实际上我收到了两个错误。

关于将变量标记为protocol Titleable: class { @objc dynamic var title: String { get set } }

的一个
  

@objc只能与类的成员,@ objc协议以及类的具体扩展一起使用

...这可以通过将协议标记为@objc来解决。

但是与@objc关键字

仍然存在错误
  

只有类的成员可以是动态的

...我认为当我限制类协议时,应该没问题,但是...不是。

我通过删除dynamic@objc关键字解决了问题

dynamic

...有效。我可以在实现此协议的类中将变量标记为protocol Titleable: class { var title: String { get set } }

@objc dynamic

但是,我不确定这为什么起作用,以及为什么在协议声明中将变量标记为class Item: Object, Titleable { @objc dynamic var title: String = "" } 无效。我将不胜感激。

1 个答案:

答案 0 :(得分:3)

看看dynamic means是什么

  

动态

     

将此修饰符应用于可以表示的类的任何成员   由Objective-C。当您使用动态标记成员声明时   修饰符,始终使用来动态调度对该成员的访问   Objective-C运行时。永远不会内联访问该成员,或者   由编译器进行虚拟化。

     

因为调度了标有dynamic修饰符的声明   使用Objective-C运行时,必须将它们标记为objc   属性。

特别考虑第一段。它说标记为dynamic的内容不能静态分派。现在考虑在模块中有一些类的情况。它已经被编译,并且它的方法是静态分配的。现在考虑另一个使该类符合某个协议的模块,该协议包括一个dynamic方法。那怎么办?该方法已经已经在某些地方静态分配。它不能追溯地转换为动态调度。 (根据编译器标志和访问级别,相同的内容也可以应用于同一模块中的声明,但我发现更容易解释跨模块。)

无论如何,您要这样做的主要原因是要确保可以在该属性上使用KVO。 (如果有其他原因,您需要强制让符合类型使用动态属性,我很想知道用例。)如果这是您的目标,则可能需要Titleable符合{{ 1}}。