Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Class Swift:实现协议的UIView子类的属性_Class_Swift_Properties_Polymorphism_Protocols - Fatal编程技术网

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时,该变量会被赋值?