Use Generic Protocol to filter array of subviews

@jonprescott also posted the question on StackOverflow: https://stackoverflow.com/questions/57443837/use-generic-protocol-to-filter-array-of-subviews just in case we'll find an answer. Seems like a trivial thing at glance. Any chance you have another trick in the sleeve? ah
Thank you for your help, Jonathan!

Try this:

for view in superview.subviews
{
	print("\(view as! ViewItem<CanvasItem>).canvasItem.scale)")
}

Crashing with:
Could not cast value of type '__lldb_expr_1.CanvasStickerView' (0x123151478) to '__lldb_expr_1.ViewItem<__lldb_expr_1.CanvasItem>' (0x10d2d7d20).

This seems to work (just printed out first view).

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

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

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

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

class ViewItem : UIView
{
	let canvasItem: CanvasItemProtocol
	init(_ item: CanvasItemProtocol)
	{
		canvasItem = item
		super.init(frame: .zero)
	}
	
	required init?(coder aDecoder: NSCoder) {
		fatalError("init(coder:) has not been implemented")
	}
}

let shapeItem = ShapeItem()
let stickerItem = StickerItem()
print("\(stickerItem.scale)")
let shapeView = ViewItem(shapeItem)
let stickerView = ViewItem(stickerItem)
print("\(stickerView.canvasItem.scale)")

let superview = UIView()
superview.addSubview(shapeView)
superview.addSubview(stickerView)

print("\((superview.subviews[0] as! ViewItem).canvasItem.scale)")

The issue is that you can't inherit through a base class for the generic type parameter. So, ViewItem<StickerItem> is not related to ViewItem<CanvasItem>, even though the generic parameters have an inheritance relationship. They are distinct types. So, the solution is to no constrain ViewItem, which makes a certain amount of sense.

Yap, seems Gnereics doesn't help us so much in this example. Is it possible to still use subclasses CanvasShapeView , CanvasStickerView for specific implementations, and still use this mechanism?
And create some kind of a BaseClass so we won't need to repeat code for each class?

As long as CanvasShapeView, CanvasStickerView, etc., inherit from ViewItem (maybe should be renamed to CanvasItemView?).

Note that CanvasItem is the base class for the ...Item hierarchy. ViewItem is a base class for the Canvas...View hierarchy. You can also add classes in between to encapsulate common code at various levels.

Terms of Service

Privacy Policy

Cookie Policy