0

How can I have a variable in Swift that has the following restrictions:

  1. It must conform to a specific protocol
  2. It must be a subclass of UIView
  3. It does not need to be a direct subclass child of UIView (i.e. it may be a subclass of a UIButton, for example)

Note that this is similar to this (which fails to satisfy point 3).

The following also satisfies points 1 and 2 (but not 3):

protocol MyProtocol {
    var onClick: Void -> Void {get set}
}

class MyCommonView: UIView, MyProtocol {
    var onClick: Void -> Void = {
        println("onClick!")
    }
}

class MyLittleView: MyCommonView {

}

class MyBigView: MyCommonView {

}

var myView: MyProtocol!
myView = MyLittleView()
myView.onClick()
myView.backgroundColor = UIColor.redColor()  // 'MyProtocol' does not have a member named 'backgroundColor' 

myView = MyBigView()
myView.onClick()
myView.backgroundColor = UIColor.redColor()  // 'MyProtocol' does not have a member named 'backgroundColor' 

Edit Although this is similar to this question (and answer by @zneak), it would be great to not have to specify all the UIView methods that I want to use, I'd like to be able to use any or all of them.

Here is what I came up with based on the answer given by @zneak, can it be improved so as not to have to specify all the needed UIView methods I want to use?

protocol MyOnClickProtocol {
    var onClick: Void -> Void {get set}
}

protocol MyViewProtocol {
    var backgroundColor: UIColor? {get set}
    // And other methods or properties of UIView that I want to access...
}

class MyLittleView: UIButton, MyOnClickProtocol, MyViewProtocol {
    var onClick: Void -> Void = {
        println("onClick!")
    }
}

class MyBigView: UISwitch, MyOnClickProtocol, MyViewProtocol {
    var onClick: Void -> Void = {
        println("onClick!")
    }
}

var myView: protocol<MyViewProtocol, MyOnClickProtocol>!
myView = MyLittleView()
myView.onClick()
myView.backgroundColor = UIColor.redColor()

myView = MyBigView()
myView.onClick()
myView.backgroundColor = UIColor.redColor()
Community
  • 1
  • 1
paulvs
  • 11,963
  • 3
  • 41
  • 66
  • 1
    Same as [Make property of type and also conform to protocol in Swift](http://stackoverflow.com/questions/29881621/make-property-of-type-and-also-conform-to-protocol-in-swift)? – zneak Sep 03 '15 at 22:16
  • @zneak, it is not the same because I wanted `myView ` to inherit all the properties and methods of `UIView`. My updated solution (based on your answer), requires the methods I want to use to be explicitly specified in the protocol, which doesn't seem like inheritance at all, that's why I never thought of putting them in a protocol, which is like a white-list of methods to accept. – paulvs Sep 04 '15 at 19:12
  • I believe that it is the same problem, and the answer was "there's no way to do that currently". Manually specifying methods is a workaround. – zneak Sep 04 '15 at 19:26
  • I understand that there could be no way to do this at the moment, but I'll keep looking. Manually specifying the methods is not a workaround in all cases I realised, like if you want to pass `myView` to a method that accepts a `UIView`. – paulvs Sep 07 '15 at 12:48
  • No problem. Consider adding another answer to the linked question if you find something. – zneak Sep 07 '15 at 15:42

0 Answers0