【问题标题】:Swift conform to protocol subclassSwift 符合协议子类
【发布时间】:2019-06-29 09:28:47
【问题描述】:

在我的应用程序中,我有多个依赖于模型的 UIView 子类。每个采用'Restorable'协议的类都包含模型的超类。每个子模型都描述了特定的 UIView 不常见属性。

// Super-model
public protocol StoryItem {
    var id: Int64? { get }
}

// Parent protocol
public protocol Restorable: AnyObject {
    var storyItem: StoryItem? { get set }
}

// Specific protocol
public struct TextItem: StoryItem {
    public var id: Int64?
    public var text: String?
}

// Not complling
class ResizableLabel: UILabel, Restorable {
    var storyItem: TextItem?
}

我收到以下编译器错误:

*Type 'ResizableLabel' does not conform to protocol 'Restorable'*

我可以让它编译的唯一方法是将ResizableLabel更改为

// Works
class ResizableLabel: UILabel, Restorable {
    var storyItem: StoryItem?
}

有什么方法可以符合协议子类吗?它会使 Init 过程更加干净。感谢您的帮助!

【问题讨论】:

  • 嘿@matt,谢谢你的回复。我已经更新了代码以更清晰。另外,我将 TextItem 更改为结构而不是协议。在我的应用程序中,我可以创建标签、图像。贴纸等'。它们中的每一个都是使用不同的模型构建的。但是所有模型都有一个超类模型,它们共享共同的属性。当我向 UIView 子类添加模型时,假设是标签。我想指定该对象从 TextModel 获取他的数据(这就是我将 storyItem 类更改为 TextItem 的原因。
  • @matt 现在,例如,当我创建标签对象时,我正在创建 TextItem 并将其分配给 storyItem (最底层的代码行),并且每次我想访问它,我需要强制转换它,我试图避免这种情况

标签: ios swift inheritance protocols subclass


【解决方案1】:

改变

public protocol Restorable: AnyObject {
    var storyItem: StoryItem? { get set } // adopter must declare as StoryItem
}

public protocol Restorable: AnyObject {
    associatedtype T : StoryItem
    var storyItem: T? { get set } // adopter must declare as StoryItem adopter
}

现在您的代码可以编译了。完整示例:

public protocol StoryItem {
    var id: Int64? { get }
}
public protocol Restorable: AnyObject {
    associatedtype T : StoryItem
    var storyItem: T? { get set }
}
public struct TextItem: StoryItem {
    public var id: Int64?
    public var text: String?
}
class ResizableLabel: UILabel, Restorable {
    var storyItem: TextItem? // ok because TextItem is a StoryItem adopter
}

【讨论】:

  • 添加了解释你所说的和你想说的之间的区别的 cmets。
  • 嘿@matt,小的后续问题。假设我有一个 UIView,其中包含贴纸、图像、标签作为其他类的子视图。我只想获得采用“可恢复”子视图的子视图。所以我尝试了类似的方法:让restorableSubviews = view.subviews.compactMap({$0 as?(Restorable & UIView)})。但我收到编译错误:协议“可恢复”只能用作通用约束,因为它具有自我或相关类型要求。||我需要以不同的方式投射它们吗?
  • 顺便说一句,如果您认为我需要发布另一个问题,请告诉我,我会立即进行。
  • 为了满足您在这个问题中的要求,我们不得不将 Restorable 设为通用约束。现在它不能用作类型。最简单的解决方案是声明一个只有 Restorable 采用的空协议,并使用 that 作为您的类型名称(尽管稍后您必须放弃)。但这不是唯一的解决方案。搜索那个错误,你会发现这已经在 Stack Overflow 上进行了彻底的讨论,所以没有必要提出一个新问题——它会是重复的。
  • 感谢您的回复!我应该为每个对象(标签/图像/贴纸)这样做吗?还是用一种协议来统治它们?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多