在Objective-C中,可以编写类似的东西:
@property(retain) UIView<Protocol1, Protocol2, ...> *myView;
但是如何在swift中编写这段代码?
我已经知道如何使属性符合许多协议,但是使用继承它不起作用:
var myView: ??? protocol<Protocol1, Protocol2, ...>
修改
我使用了许多UIView
个子类型,例如UIImageView
,UILabel
或其他,我需要使用一些UIView
属性以及协议中定义的一些方法。在最坏的情况下,我可以创建一个具有所需属性的UIViewProtocol
,但我知道在Swift中是否可以使用类型和某些协议来声明属性/变量。
答案 0 :(得分:25)
您可以使用where clause:
对通用类执行此操作使用where子句可以要求关联的类型符合 到某个协议,和/或某些类型参数和 相关类型是相同的。
要使用它,请在具有type constraint的泛型类中定义属性,以检查属性的type parameter是否与所需的基类和协议匹配。
对于您的具体示例,它可能看起来像这样:
class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
var myView: T
// ...
}
答案 1 :(得分:6)
在Swift 4中,它终于有可能了。您可以同时声明某些符合协议的类的变量,如下所示:
class ClassA {
var someVar: String?
}
protocol ProtocolA {}
class ClassB {
var someOptional: (ClassA & ProtocolA)? // here is optional value
var some: ClassA & ProtocolA // here is non-optional value; need to provide init though :)
}
答案 2 :(得分:5)
为UIView
创建一个包装协议,其中一个可能有点丑陋的方法是:
protocol UIViewRef {
var instance: UIView { get }
}
现在可以创建一个实现Protocol1
,Protocol2
和UIViewRef
的协议,该协议将用于获取UIView
本身:
protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }
最后一步将为您的UIView
实施UIViewRef协议,根据您的理解,我已经实现了Protocol1
和Protocol2
:
// SomeOfMyViews already implements Protocol1 and Protocol2
extension SomeOfMyUIViews: MyUIViewProtocol {
var instance: UIView { return self }
}
结果我们有MyUIViewProtocol
,其实施者持有UIView
的引用,并且每个实现者都实现
Protocol1
和Protocol2
。但有一点需要注意 - 要获得UIView
本身,我们需要从instance
询问它的引用
属性。例如
// Lets say we're somewhere in a UIViewController
var views: [SomeOfMyUIView] = // Get list of my views
views.forEach { self.view.addSubview($0.instance) }