3
votes

I want to create a base class for UIViews that require that a delegate conform to a specific protocol defined by the View.

class BaseView<P>: UIView {
    weak var delegate: P?
}

protocol MyProtocol {}

class MyView: BaseView<MyProtocol> {}

This gives me the error: "'weak' must not be applied to non-class-bound 'T'; consider adding a protocol conformance that has a class bound".

How do I fix this error? Or is there some work around? Or is it not so necessary to make the delegate variable weak in the first place? Thanks in advance.

2

2 Answers

5
votes

Since weak is a property assigned to anything that is of class type and not struct, you have to explicitly constraint your generic parameter to be of class type and you do that this way:

class BaseView<P: AnyObject>: UIView {
    weak var delegate: P?
}

@objc protocol MyProtocol {

}

class MyView: BaseView<MyProtocol> {

}

Only one need of clarification. Usually to make a protocol be of class type usally you would make it conform to class this way:

protocol MyProtocol: class { }

However, for some reason the compiler throws an error if you were to do it that way. I learned that this is a bug that could be learned about more here:

How to require that a protocol can only be adopted by a specific class

So adding the @objc helps silence the warning and error both.

1
votes

You should add type constraint to your generic by adding MyProtocol and create a class that conforms MyProtocol.

You can find more info here.

Updated code:

class BaseView<P: MyProtocol>: UIView {
    weak var delegate: MyProtocol?
}

protocol MyProtocol: class {}

class MyProtocolImp: MyProtocol {

}

class MyView: BaseView<MyProtocolImp> {

}

But I don't know why you use P parameter in class. You can write without this:

class BaseView: UIView {
    weak var delegate: MyProtocol?
}

protocol MyProtocol: class {}

class MyView: BaseView {

}