使用通用协议过滤子视图数组
Use Generic Protocol to filter array of subviews
在我们的应用程序中,我们有一个 canvas。 canvas 可以包含贴纸、图像、文本等。我们有一个协议 CanvasItem
可以实现这些项目之间的共同属性:
protocol CanvasItemProtocol{
var scale : CGFloat { get set }
}
class CanvasItem : CanvasItemProtocol {
public var scale : CGFloat = 1.0
}
然后每个 class-模型(贴纸、文本等)符合 CanvasItem
,添加 class-特定属性:
public class StickerItem: CanvasItem {
public var stickerName: String
}
public class ShapeItem: CanvasItem {
public var shapeColor: UIColor
}
为了展示这些,我们首先创建了一个基础泛型(我认为)UIView
class 只能用 CanvasItem
:
初始化
class ViewItem <T: CanvasItemProtocol>: UIView {
let canvasItem: T
init (t: T) {
self.canvasItem = t
super .init(frame: .zero)
}
}
然后对于每个模型,我们创建特定的 UIView<CanvasItem>
class:
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({[=14=] as? ViewItem<CanvasItem>}) {
print(canvasItemView.canvasItem.scale) // **access only the common properties**
}
可以编译,但是 return 结果为零(转换不工作)...
我试图只访问 CanvasItem
公共属性 .
要点link:
Playground.swift
有什么建议吗?我们坚持这个好几天了。
非常感谢任何帮助。
协议和泛型与 subclassing 一起不能很好地协同工作
实际上您既不需要协议也不需要视图包装器class。 Subclassing 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)
}
类 CanvasShapeView
和 CanvasStickerView
共享 class 的模板,但完全不同 classes.
这就是为什么我要检查 class 是否符合相同的模板 - 搜索 canvasItem
作为 class 的一部分,然后尝试获取需要的值:
let test = superview.subviews
.compactMap({ Mirror(reflecting: [=10=]).children.first(where: { [=10=].label == "canvasItem" }) })
.compactMap({ [=10=].value as? CanvasItemProtocol })
for value in test {
print(value.scale)
}
为了做到这一点,我不得不使用反射 - 我猜这不是最好的解决方案,但它确实起到了作用。
在我们的应用程序中,我们有一个 canvas。 canvas 可以包含贴纸、图像、文本等。我们有一个协议 CanvasItem
可以实现这些项目之间的共同属性:
protocol CanvasItemProtocol{
var scale : CGFloat { get set }
}
class CanvasItem : CanvasItemProtocol {
public var scale : CGFloat = 1.0
}
然后每个 class-模型(贴纸、文本等)符合 CanvasItem
,添加 class-特定属性:
public class StickerItem: CanvasItem {
public var stickerName: String
}
public class ShapeItem: CanvasItem {
public var shapeColor: UIColor
}
为了展示这些,我们首先创建了一个基础泛型(我认为)UIView
class 只能用 CanvasItem
:
class ViewItem <T: CanvasItemProtocol>: UIView {
let canvasItem: T
init (t: T) {
self.canvasItem = t
super .init(frame: .zero)
}
}
然后对于每个模型,我们创建特定的 UIView<CanvasItem>
class:
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({[=14=] as? ViewItem<CanvasItem>}) {
print(canvasItemView.canvasItem.scale) // **access only the common properties**
}
可以编译,但是 return 结果为零(转换不工作)...
我试图只访问 CanvasItem
公共属性 .
要点link: Playground.swift
有什么建议吗?我们坚持这个好几天了。
非常感谢任何帮助。
协议和泛型与 subclassing 一起不能很好地协同工作
实际上您既不需要协议也不需要视图包装器class。 Subclassing 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)
}
类 CanvasShapeView
和 CanvasStickerView
共享 class 的模板,但完全不同 classes.
这就是为什么我要检查 class 是否符合相同的模板 - 搜索 canvasItem
作为 class 的一部分,然后尝试获取需要的值:
let test = superview.subviews
.compactMap({ Mirror(reflecting: [=10=]).children.first(where: { [=10=].label == "canvasItem" }) })
.compactMap({ [=10=].value as? CanvasItemProtocol })
for value in test {
print(value.scale)
}
为了做到这一点,我不得不使用反射 - 我猜这不是最好的解决方案,但它确实起到了作用。