Class Swift:实现协议的UIView子类的属性
下面是一个场景。根据向用户显示的模型对象,我有许多不同的视图要显示。所以我建立了一个协议,任何实现它的视图都可以被呈现出来Class Swift:实现协议的UIView子类的属性,class,swift,properties,polymorphism,protocols,Class,Swift,Properties,Polymorphism,Protocols,下面是一个场景。根据向用户显示的模型对象,我有许多不同的视图要显示。所以我建立了一个协议,任何实现它的视图都可以被呈现出来 class MyItem { /* some model properties */ } protocol ItemView: class { // some protocol methods (e.g. updateWithItem(), etc) func setupItem(item: MyItem) } class SpecificItemVie
class MyItem { /* some model properties */ }
protocol ItemView: class {
// some protocol methods (e.g. updateWithItem(), etc)
func setupItem(item: MyItem)
}
class SpecificItemView: UIView, ItemView { /* there will be multiple classes like this */
func setupItem(item: MyItem) {
// do item setup
}
}
class AnotherItemView: UIView, ItemView {
func setupItem(item: MyItem) {
// do DIFFERENT item setup
}
}
然后,当我在视图控制器中使用它们时,我得到了一个ItemView类:
class MyViewController: UIViewController {
var itemView: ItemView? // could be a SpecificItemView or AnotherItemView
override func viewDidLoad() {
itemView?.setupItem(MyItem())
itemView?.removeFromSuperview() /* this line won't compile */
}
}
除了最后一行,我尝试调用一个UIView
方法(removeFromSuperview
)。这并不奇怪,因为ItemView
与UIView
没有关系
在目标C中,我将通过如下方式指定我的itemView ivar来解决此问题:
@property (nonatomic, strong) UIView<ItemView> *itemView;
@property(非原子,强)UIView*itemView;
但我似乎找不到类似的Swift语法。我怀疑没有办法在Swift中使用这种模式。如何以快速友好的方式实现我的UIView类的总体目标
到目前为止,我找到的一个黑客解决方案是将我调用的任何UIView
方法(例如removeFromSuperview
)添加到我的ItemView
协议中
我从中得到的另一个建议(并非如此)是创建一个
UIView
子类,实现ItemView
协议,specifictitemview
和AnotherItemView
。你可以看到。虽然这解决了将类和协议封装在单一类型(例如,var itemView:ItemViewParentClass
)中的问题,但它基本上使协议毫无意义,因为您现在正在父类中实现所有协议的方法,并在子类中重写它们。这种解决方案的一个最大缺点是,当您在视图控制器中引用子类(SpecificItemView
)时,必须将子类的实例强制转换为新的hypthetical父类(ItemViewParentClass
)。ItemView
不扩展UIView
,但是您的SpecificItemView
确实如此。当然,您的ItemView
上不存在removeFromSuperView
在ViewController中,您声明了一个ItemView
type对象,而不是SpecificItemView
将MyViewController
代码更改为:
var itemView:SpecificItemView?
正如您所发现的,无法同时为对象指定类和协议 解决此问题的最简单方法是将
removeFromSuperview
(以及您需要确保的任何其他UIView
方法都存在)添加到您的协议中。也许以下(在Swift 4中)可以解决此问题
class MyViewController: UIViewController {
typealias T = UIView & ItemView
var itemView: T?
}
从Swift 5开始,通过将您的协议限制为仅应用于
ui视图
,这是可能的。为此,只需执行以下操作:
protocol ItemView: UIView {
func setupItem(item: MyItem)
}
通过将此约束添加到协议中,swift编译器识别为ItemView
的任何对象也将具有所有UIView
方法
类似地,如果非
UIView
子类试图实现ItemView
协议,您的代码将无法编译。编译器发出的错误消息是什么?您的ItemView没有扩展UIView您的示例代码需要更改为var ItemView:specifictitemview?
@Aggressor稍微澄清了我的问题。需要支持多个子类。那就行了,除了这里的目标是拥有两个不同的SpecificItemView
类,例如SongItemView
和AlbumItemView
你能告诉我为什么ItemView一开始不扩展UIView吗?我看不出有什么好的理由(但可能有!),但假设有,您是否可以创建自己的remove()函数,并且在实例化子类时,分配该成员变量并调用remove?因此,ItemView有一个通用视图成员变量,当您调用setupItem时,该变量会被赋值?