I am encountering a weird bug lately, while trying to conform a class to a given protocol the compiler rejects the typealias declaration.
My code looks like this:
/// Protocol from CareKit
public protocol OCKTaskViewSynchronizerProtocol: OCKAnyTaskViewSynchronizerProtocol {
associatedtype View: UIView & OCKTaskDisplayable
func makeView() -> View
func updateView(_ view: View, context: OCKSynchronizationContext<OCKTaskEvents?>)
}
/// My own protocol
protocol ConditionalTaskViewProtocol: UIView, OCKTaskDisplayable, OCKEventUpdatable {
init()
}
/// class that should conform to `OCKTaskViewSynchronizerProtocol`
/// Error gets thrown here:
/// Type 'ConditionalTaskViewSynchronizer<First, Second>' does not conform to protocol 'OCKTaskViewSynchronizerProtocol'"
class ConditionalTaskViewSynchronizer<First: ConditionalTaskViewProtocol, Second: ConditionalTaskViewProtocol>: OCKTaskViewSynchronizerProtocol {
typealias View = ConditionalTaskViewProtocol
let condition: () -> Bool
public init(condition: @escaping () -> Bool) {
self.condition = condition
}
func makeView() -> View {
if condition() {
return First()
} else {
return Second()
}
}
func updateView(_ view: View, context: OCKSynchronizationContext<OCKTaskEvents?>) {
view.updateWith(event: context.viewModel?.firstEvent, animated: context.animated)
}
}
The fix that the compiler suggests is to conform the type of the typealias View to UIView. But I already conformed ConditionalTaskViewProtocol to both UIView and OCKTaskDisplayable.
Am I missing something here?
Help would be highly appreciated!
View needs to be a concrete type that inherits from UIView and conforms to OCKTaskDisplayable.
Thanks for the fast response @suyashsrijan!
But to be honest I am not quite sure how I can replace the protocol with a concrete type at that point.
I specifically used a protocol to be able to conform specific views to it and then present them based on a specified condition. Can I achieve the same functionality with a concrete type of some sorts?
jonprescott
(Jonathan Prescott)
4
I think you need to transform:
protocol ConditionalTaskViewProtocol
to
class ConditionalTaskView
which is the concrete class you need. Declaring it as a class makes it derive from UIView, which the framework wants. Then, First and Second are defined as sub-classes of ConditionalTaskView.
Karl
(👑🦆)
5
If you look at your “makeView” method, it returns two different types (First or Second) depending on whether the condition is true or false. That needs to become a single return type.
That single view type can be generic, and can simply host one of the given views, full-size, depending on the condition. So basically you sink that logic down to the view.