Type does not conform to protocol
viewForValue
is supposed to return a class which inherits from UIView
and implements SomeProtocol
.
You have defined 2 classes having no direct relationship - they just inherit from UIView
and implement SomeProtocol
.
When the function has to determine the return type, the direct concrete type both classes inherit from is UIView
, so that is what viewForValue
returns.
In order to fix the problem, you have to create a direct and concrete relationship between the 2 classes, by creating a 3rd class inheriting from UIView
and implementing SomeProtocol
:
protocol SomeProtocol {
func setValue(value: Int)
}
class SomeClass: UIView, SomeProtocol {
func setValue(value: Int) {
}
}
class SomeSubclass : SomeClass {
}
class SomeOtherSubclass : SomeClass {
}
func viewForValue<T where T: SomeProtocol, T: SomeClass>(param: Int) -> T {
var someView: T
if param > 0 {
someView = SomeSubclass() as T
} else {
someView = SomeOtherSubclass() as T
}
someView.setValue(2)
someView.frame = CGRectZero
return someView
}
viewForValue(2)
Addendum: reading the OP comment below, the purpose is to dynamically instantiate existing UIKit classes inheriting from UIView
. So the proposed solution doesn't apply.
I think that extending UIView
by implementing SomeProtocol
should work:
protocol SomeProtocol {
func setValue(value: Int)
}
extension UIView : SomeProtocol {
func setValue(value: Int) {
}
}
func viewForValue<T where T: SomeProtocol, T: UIView>(param: Int) -> UIView {
var someView: T
if param > 0 {
someView = UILabel() as T
} else {
someView = UIImageView() as T
}
someView.setValue(2)
someView.frame = CGRectZero
return someView
}
but it looks like there's a compiler bug. This code in a playground shows a message stating that:
Communication with the playground service was interrupted unexpectedly. The playground service "com.apple.dt.Xcode.Playground" may have generated a crash log.
whereas in an iOS application compilation fails due to a segmentation fault 11.
Kamchatka
Updated on June 21, 2022Comments
-
Kamchatka almost 2 years
I'm still having trouble understanding some subtleties of generics in Swift. I define the following types:
protocol SomeProtocol { func setValue(value: Int) } class ProtocolLabel : UILabel, SomeProtocol { func setValue(value: Int) { } } class ProtocolImageView : UIImageView, SomeProtocol { func setValue(value: Int) { } }
viewForValue(2) Now I defined the following function. I expect T to be a UIView that conforms to protocol SomeProtocol.
func viewForValue<T where T: SomeProtocol, T: UIView>(param: Int) -> UIView { var someView: T if param > 0 { someView = ProtocolLabel() as T } else { someView = ProtocolImageView() as T } someView.setValue(2) someView.frame = CGRectZero return someView }
However, I'm getting the following compile error when I execute the code:
viewForValue(2) // <-- Type 'UIView' does not conform to protocol 'SomeProtocol'
It seems that in the where clause I can't specify a class that does not implement the protocol. Why is that?
Thanks in advance.