在我们的应用程序中,我们有一个画布。画布可以包含贴纸,图像,文本等。我​​们有一个协议CanvasItem来实现这些项目之间的 public 属性:

protocol CanvasItemProtocol{
  var scale : CGFloat { get set }
}

class CanvasItem : CanvasItemProtocol {
   public var scale : CGFloat = 1.0
}

然后,每个类模型(Stickers,Text等)都符合CanvasItem,并添加特定于类的属性:
public class StickerItem: CanvasItem {
  public var stickerName: String
}

public class ShapeItem: CanvasItem {
  public var shapeColor: UIColor
}

为了显示这些,我们首先创建了一个基本的(我认为)基本UIView类,该类只能用CanvasItem初始化:
class ViewItem <T: CanvasItemProtocol>: UIView {
let canvasItem: T
init (t: T) {
    self.canvasItem = t
    super .init(frame: .zero)
  }
}

然后为每个模型创建特定的UIView<CanvasItem>类:
class CanvasShapeView: ViewClass<ShapeItem> { }

class CanvasStickerView: ViewClass<StickerItem> { }

然后,我尝试执行以下操作:
let superview = UIView()
let shapeView = CanvasStickerView(StickerItem())
let stickerView = CanvasShapeView(ShapeItem())

superview.addSubview(shapeView)
superview.addSubview(stickerView)

for canvasItemView in superview.subviews.compactMap({$0 as? ViewItem<CanvasItem>}) {
   print(canvasItemView.canvasItem.scale) // **access only the common properties**
}

编译,但返回零结果(强制转换不起作用) ...
我正在尝试仅访问CanvasItem 公用属性

要点链接:
Playground.swift

有什么建议么?我们现在坚持了好几天。

任何帮助将不胜感激。

最佳答案

协议和泛型与子类结合使用效果不佳

实际上,您既不需要协议,也不需要视图包装器类。子类化UIView就足够了。

class CanvasItem : UIView
{
    public var scale : CGFloat = 1.0
}

class StickerItem: CanvasItem
{
    public var stickerName : String = ""
}

class ShapeItem: CanvasItem
{
    public var color: UIColor = .red
}

let shapeItem = ShapeItem()
let stickerItem = StickerItem()
let superview = UIView()
superview.addSubview(shapeItem)
superview.addSubview(stickerItem)

for case let canvasItemView as CanvasItem in superview.subviews {
    print(canvasItemView.scale)
}

关于ios - 使用通用协议(protocol)过滤 subview 数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57443837/

10-10 21:38