首页 文章

Swift:属性符合特定类,同时符合多个协议

提问于
浏览
31

在Objective-C中,可以编写类似的东西:

@property(retain) UIView<Protocol1, Protocol2, ...> *myView;

但是如何在swift中编写这段代码呢?

我已经知道如何使属性符合许多协议,但它不能使用继承:

var myView: ??? protocol<Protocol1, Protocol2, ...>

Edit:

我使用了许多 UIView 子类,如 UIImageViewUILabel 或其他,我需要使用一些 UIView 属性以及协议中定义的一些方法 . 在最坏的情况下,我可以创建一个具有所需属性的 UIViewProtocol ,但我知道在Swift中是否可以使用类型和一些协议来声明属性/变量 .

3 回答

  • 5

    您可以使用where clause使用泛型类来执行此操作:

    where子句使您能够要求关联类型符合某个协议,和/或某些类型参数和相关类型是相同的 .

    要使用它,请使用type constraint在类的属性中定义属性,以检查属性的type parameter是否与所需的基类和协议匹配 .

    对于您的具体示例,它可能看起来像这样:

    class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
        var myView: T
    
        // ...
    }
    
  • 24

    一个也许有点丑陋的方法之一就是为 UIView 创建一个包装器协议:

    protocol UIViewRef {
        var instance: UIView { get }
    }
    

    现在可以创建一个实现 Protocol1Protocol2UIViewRef 的协议,该协议将用于获取 UIView 本身:

    protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }
    

    最后一步将为您的 UIView 实现UIViewRef协议,在您的情况下,据我所知,已经实现 Protocol1Protocol2

    // SomeOfMyViews already implements Protocol1 and Protocol2
    extension SomeOfMyUIViews: MyUIViewProtocol {
        var instance: UIView { return self }
    }
    

    结果我们有 MyUIViewProtocol ,其实现者持有对 UIView 的引用,并且每个实现者都实现 Protocol1Protocol2 . 但有一点需要注意 - 为了得到 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) }
    
  • 5

    在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 :)
    }
    

相关问题