Swift 动态变量不能是 Printable 类型

Posted

技术标签:

【中文标题】Swift 动态变量不能是 Printable 类型【英文标题】:Swift dynamic variable can't be of type Printable 【发布时间】:2014-10-14 22:54:59 【问题描述】:

我有一个 Swift 项目,其中包含两个 UITableViewControllers。第二个UITableViewController 链接到名为Model 的MVC 模型。根据我在第一个UITableViewController中选择的UITableViewCell,我想用IntsStrings初始化Model的一些属性。因此,我决定使用Printable 协议类型定义这些属性。同时,我想对这些属性之一执行键值观察。

现在,Model 看起来像这样:

class Model: NSObject 

    let title: String
    let array: [Printable]
    dynamic var selectedValue: Printable //error message

    init(title: String, array: [Printable], selectedValue: Printable) 
        self.title = title
        self.array = array
        self.selectedValue = selectedValue
    


这里的问题是selectedValue声明行出现以下错误信息:

属性不能标记为动态,因为它的类型不能 用Objective-C表示

如果我转到 Xcode 问题导航器,我还可以阅读以下行:

协议“可打印”不是“@objc”

有什么解决办法吗?

【问题讨论】:

您正在使用 KVO,因此您应该从 Objective-C 的角度来看待它。如果这是 Objective-C,你会如何声明 selectedValue 好吧,好问题。我敢打赌我会使用id... 查看这个答案***.com/questions/27319588/… 【参考方案1】:

没有办法做你想做的事。非@objc 协议不能在 Objective-C 中表示。一个原因是 Non-@objc 协议可以表示非类类型(实际上,你说过你想将它用于IntString,这两种类型都是非类类型)和 Objective-C 中的协议仅适用于对象。

KVO 是为 Objective-C 设计的一个特性,所以你必须从 Objective-C 的角度考虑你期望它看到什么。如果您在 Objective-C 中执行此操作,您将不希望拥有一个可以是像 id 这样的对象或像 int 这样的非对象的属性——您甚至不能声明它。相反,正如您在评论中所说,您可能希望它只是对象。并且您希望能够使用 Foundation 的桥接将Int 转换为NSNumber *String 转换为NSString *。这些是继承自 NSObject 的常规 Cocoa 类,它实现了 Printable

所以在我看来你应该只使用NSObjectNSObjectProtocol

【讨论】:

【参考方案2】:

不幸的是,ObjC 不将协议视为类型,它们只是对成员进行分组的一种方便方式。它们实际上是 Any 类型,因此很遗憾,您必须将属性设为 Any 并转换为 Printable。

我能做到的最好的事情是:

dynamic var selectedValue: Any
var printableValue : Printable 
  get 
    return (Printable)selectedValue
  
  set 
    selectedValue = newValue
  
 

【讨论】:

当然,Objective-C 将协议视为类型,但仅限于 @objc 协议。

以上是关于Swift 动态变量不能是 Printable 类型的主要内容,如果未能解决你的问题,请参考以下文章

Swift 属性

Objective-C

EXC_BAD_INSTRUCTION 对象数组赋值 Swift

java中静态类和动态类的区别的啥?

@objc 动态变量在 Swift 4 中是啥意思

Runtime objc4-779.1 为什么不能向一个已存在的类添加成员变量?有什么办法达到相同的效果?