Swift: Property conforming to a specific class and in the same time to multiple protocols

前端 未结 3 675
生来不讨喜
生来不讨喜 2020-12-05 04:22

In Objective-C, it\'s possible to write something like that:

@property(retain) UIView *myView;

But how can

相关标签:
3条回答
  • 2020-12-05 05:04

    One and probably a bit ugly one of the ways to do that, is to create a wrapper protocol for UIView:

    protocol UIViewRef {
        var instance: UIView { get }
    }
    

    Now it is possible to create a protocol which implements Protocol1, Protocol2 and UIViewRef, which is going to be used to get the UIView itself:

    protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }
    

    And last step will be implementing UIViewRef protocols for your UIViews, which, in you case, as I understand, already implement Protocol1 and Protocol2:

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

    As the result we have MyUIViewProtocol, implementers of which hold a reference to a UIView and each of them implement Protocol1 and Protocol2. One caveat though - to get the UIView itself, we need to ask it's reference from instance property. For example

    // Lets say we're somewhere in a UIViewController
    var views: [SomeOfMyUIView] = // Get list of my views
    views.forEach { self.view.addSubview($0.instance) }
    
    0 讨论(0)
  • You can do this with a generic class using a where clause:

    A where clause enables you to require that an associated type conforms to a certain protocol, and/or that certain type parameters and associated types be the same.

    To use it, make the class your property is defined in a generic class with a type constraint to check if the type parameter for your property matches your desired base class and protocols.

    For your specific example, it could look something like this:

    class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
        var myView: T
    
        // ...
    }
    
    0 讨论(0)
  • 2020-12-05 05:11

    In Swift 4 it's finally possible. You can declare variable of some class conforming to protocol at the same time, like this:

    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 :)
    }
    
    0 讨论(0)
提交回复
热议问题