1

So I wrote a simple protocol:

protocol PopupMessageType{
    var cancelButton: UIButton {get set}
    func cancel()
}

and have a customView:

class XYZMessageView: UIView, PopupMessageType {
...
}

and then I currently have:

class PopUpViewController: UIViewController {

    //code...

    var messageView : CCPopupMessageView!
    private func setupUI(){
    view.addSubview(messageView)

    }

}

But what I want to do is:

class PopUpViewController: UIViewController {

    //code...

    var messageView : PopupMessageType!
    private func setupUI(){
    view.addSubview(messageView) // ERROR

    }

}

ERROR I get:

Cannot convert value of type 'PopupMessageType!' to expected argument type 'UIView'

EDIT: I'm on Swift 2.3!

mfaani
  • 33,269
  • 19
  • 164
  • 293
  • 1
    if let popupView = messageView as? UIView { view.addSubview(popupView) } else { // handle the case where messageView is not a UIView } – Lukas Oct 09 '17 at 19:02
  • Related: https://stackoverflow.com/questions/26401778/in-swift-how-can-i-declare-a-variable-of-a-specific-type-that-conforms-to-one-o – dan Oct 09 '17 at 19:58
  • Swift 2.3 is deprecated and unsupported by any current tooling...for your own sake, please upgrade. – GetSwifty Oct 09 '17 at 22:40
  • @PEEJWEEJ [When you're In Canada, the 80s (of US) don't come to Canada til like 93](http://www.imdb.com/title/tt0885872/quotes/qt0453933) – mfaani Oct 09 '17 at 22:48
  • RIP how I met your mother :( – GetSwifty Oct 09 '17 at 22:53

3 Answers3

3

Change the type of property messageView to (UIView & PopupMessageType)!

I mean

class PopUpViewController: UIViewController {

    //code...

    var messageView : (UIView & PopupMessageType)!
    private func setupUI(){
    view.addSubview(messageView) // ERROR

    }

}
Vladyslav Zavalykhatko
  • 15,202
  • 8
  • 65
  • 100
2

In Swift 4 you can do this:

typealias PopupMessageViewType = UIView & PopupMessageType

And then use PopupMessageViewType as the type of the variable.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • and if I'm not Swift 4? – mfaani Oct 09 '17 at 18:52
  • @Honey Then you'll have to create a common base class that inherits from `UIView` and implements `PopupMessageType` and inherit everything else from that base class. – Sweeper Oct 09 '17 at 18:54
  • basically make the requirement a 'special' subclass, not a protocol. Though that special subclass conforms to a protocol and is also subclassed from UIView? meh ugly. But I get it. No other easy alternative? – mfaani Oct 09 '17 at 18:58
  • @Honey as far as I'm concerned, no. – Sweeper Oct 09 '17 at 18:59
  • @Honey I suppose you can make a wrapper class around the object and provide two computed properties to access which one you need. – DerrickHo328 Oct 09 '17 at 19:15
  • @Calimari328 can you write an answer for that? – mfaani Oct 09 '17 at 19:17
2

DISCLAIMER: I do not have the swift 2.3 compiler anymore since swift 4 is the new normal for iOS development. The following code may possibly need tweaks to get it working in swift 2.3


Essentially we will be making a 2x1 mux where the two inputs are the same object. The output depends on whether you set the mux to choose the first or the second one.

// The given protocol
protocol PopupMessageType{
    var cancelButton: UIButton {get set}
    func cancel()
}

// The object that conforms to that protocol
class XYZMessageView: UIView, PopupMessageType {
    var cancelButton: UIButton = UIButton()
    func cancel() {
    }
}

// The mux that lets you choose the UIView subclass or the PopupMessageType
struct ObjectPopupMessageTypeProtocolMux<VIEW_TYPE: UIView> {
    let view: VIEW_TYPE
    let popupMessage: PopupMessageType
}

// A class that holds and instance to the ObjectPopupMessageTypeProtocolMux
class PopUpViewController: UIViewController {
    var messageWrapper : ObjectPopupMessageTypeProtocolMux<UIView>!
    private func setupUI(){
        view.addSubview(messageWrapper.view)
    }
}

//...
let vc = PopUpViewController() // create the view controller
let inputView = XYZMessageView() // create desired view

// create the ObjectPopupMessageTypeProtocolMux
vc.messageWrapper = ObjectPopupMessageTypeProtocolMux(view: inputView, popupMessage: inputView) //<-- 1

vc.messageWrapper.view // retreive the view
vc.messageWrapper.popupMessage.cancel() // access the protocol's methods
vc.messageWrapper.popupMessage.cancelButton // get the button

1) I input the "inputView" twice for the initializer of ObjectPopupMessageTypeProtocolMux. They are the same class instance, but they get casted to different types.

I hope this helps you get to where you wanna go in swift 2.3

DerrickHo328
  • 4,664
  • 7
  • 29
  • 50