2

Is it possible for swift to have a ViewController class, initialized from xib, has a property that is also a subclass of UIViewController and conforms to some protocol?

    protocol SomeProtocol {
        // Some methods
    }

    class ViewController: UIViewController {
        // contentView is initialized from xib
        @IBOutlet weak var contentView: UIView!

        // I'd like to declare anotherViewController both conforms to 'SomeProtocol' 
        // and a subclass of UIViewController
        var anotherViewController: UIViewController!
        ...
    }  

When I declare ViewController as an generic class, say class ViewController<T: UIViewController, SomeProtocol>, I get an error :

"Variable in a generic class cannot be presented in Objective-C"

So how can I fulfil it if I cannot use generic class?

Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
liuyaodong
  • 2,547
  • 18
  • 31
  • Try reversing the two i.e. class ViewController – Rajeev Bhatia Oct 29 '14 at 09:58
  • possible duplicate of [How do I declare a variable that has a type and implements a protocol?](http://stackoverflow.com/questions/25214484/how-do-i-declare-a-variable-that-has-a-type-and-implements-a-protocol) – Matthias Bauch Oct 29 '14 at 10:16
  • @MatthiasBauch I don't think the link solves my problem. I want a `UIViewController` property and it conforms to some protocol, instead of a property which conforms to some protocol and can be assigned with a subclass of `UIViewController`. – liuyaodong Oct 30 '14 at 04:29
  • @RajeevBhatia it doesn't work :( – liuyaodong Oct 30 '14 at 04:30

2 Answers2

1

Please forgive me if I misunderstood your problem, but I think what you want to do is declare a new type that inherits from UIViewController and conforms to SomeProtocol, like so:

protocol SomeProtocol { }

class VCWithSomeProtocol: UIViewController, SomeProtocol {

}

class ViewController: UIViewController {
    var anotherViewController: VCWithSomeProtocol!
}
radex
  • 6,336
  • 4
  • 30
  • 39
  • Thank you! It does solve my problem. However, I have to make lots of my view controllers subclass the `VCWithSomeProtocol`, which is not what I want. Since multiple inheritance is not supported by Swift, I may have my own inheritance hierarchy. – liuyaodong Oct 30 '14 at 04:36
0

So I hope I am not misunderstanding the question as well, but it sounds like you may want a multiple-inheritance object level mixin such as:

let myVC: ViewController, SomeProtocol

Unfortunately, Swift does not support this. However, there is a somewhat awkward work-around that may serve your purposes.

struct VCWithSomeProtocol {
    let protocol: SomeProtocol
    let viewController: UIViewController

    init<T: UIViewController>(vc: T) where T: SomeProtocol {
        self.protocol = vc
        self.viewController = vc
    }
}

Then, anywhere you need to do anything that UIViewController has, you would access the .viewController aspect of the struct and anything you need the protocol aspect, you would reference the .protocol.

For Instance:

class SomeClass {
   let mySpecialViewController: VCWithSomeProtocol

   init<T: UIViewController>(injectedViewController: T) where T: SomeProtocol {
       self.mySpecialViewController = VCWithSomeProtocol(vc: injectedViewController)
   }
}

Now anytime you need mySpecialViewController to do anything UIViewController related, you just reference mySpecialViewController.viewController and whenever you need it to do some protocol function, you reference mySpecialViewController.protocol.

Hopefully Swift 4 will allow us to declare an object with protocols attached to it in the future. But for now, this works.

Hope this helps!

Michael Curtis
  • 564
  • 3
  • 9