Andrew Ebling
Andrew Ebling

Reputation: 10283

Declare variable of type UIView conforming to a protocol in Swift 2

I need to declare a variable of type UIView which also conforms to MyProtocol:

protocol MyProtocol: class {
    func foobar()
}

class MyClass {
    var myView: UIView<MyProtocol>! // Error: Cannot specialize non-generic type 'UIView'
}

However I get the compiler error: Cannot specialize non-generic type 'UIView'.

I need to access methods on the variable from UIView and MyProtocol.

What is the correct variable declaration to support these requirements?

If it makes any difference, only UIView subclasses will implement the protocol. Currently I add protocol conformance via extensions.

I found this answer: https://stackoverflow.com/a/25771265/233602 but it's not clear if that answer is still the best option going in when writing in Swift 2.

Upvotes: 6

Views: 7890

Answers (4)

user652038
user652038

Reputation:

If it makes any difference, only UIView subclasses will implement the protocol.

It makes all the difference! Just do this:

protocol MyProtocol: UIView {
  func foobar()
}

class MyClass {
  var myView: MyProtocol!
}

Upvotes: 0

mygzi
mygzi

Reputation: 1333

Late to the party here, but SE-0156 (adopted by Swift 4) enables class and protocol composition in type declarations without requiring (resorting to?) generics.

protocol MyProtocol: class {
     func foobar()
}

class MyClass {
     var myView: (UIView & MyProtocol)!
}

Upvotes: 1

Qbyte
Qbyte

Reputation: 13243

Probably the best way to solve this is to use a protocol where all UIViews conform to:

protocol UIViewType {
    var view: UIView { get }
}

extension UIView: UIViewType {
    var view: UIView { return self }
}

// the variable
var myView: protocol<UIViewType, MyProtocol>

Use the view property to access UIView specific functionality.

Upvotes: 5

Sandeep
Sandeep

Reputation: 21144

Make your class a generic class as follows,

protocol MyProtocol: class {
    func foobar()
}

class MyClass<T:MyProtocol where T:UIView> {
    var myView: T!
}

The error above says that UIView cannot specialise to protocol MyProtocol, so, the solution here would be to make your class a generic class which takes generic parameter which conforms to MyProtocol and is subclass of UIView.

Upvotes: 10

Related Questions