Home > Mobile >  returning swift protocol associated type in multiple methods
returning swift protocol associated type in multiple methods

Time:02-04

Coming from a java/kotlin background I am trying to get my head around swift protocols with associated types. Why does the following snippet fail to compile with error: "Type ViewFactoryImpl does not conform to protocol ViewFactory" and what would be the solution?

protocol ViewFactory  {
    associatedtype V: View
    func createSomeView() -> V
    func createAnotherView() -> V
}

class ViewFactoryImpl: ViewFactory {
    
    func createSomeView() ->  some View {
        return ViewA()
    }
    
    func createAnotherView() ->  some View {
        return ViewB()
    }
}

By playing around i was able to compile by defining the following instead

protocol ViewFactory  {
    associatedtype V1: View
    associatedtype V2: View
    func createSomeView() -> V1
    func createAnotherView() -> V2
}

I do not understand the issue. I thought the associated type is defined for the entire protocol and can be used in multiple methods. What I am missing?

CodePudding user response:

  1. Each associatedtype refers to one type.
  2. ViewA and ViewB are not the same type.
  3. some does not turn them both into the same type.

And even if they were backed by the same type, you can't use multiple opaque return types to match a single associated type.

protocol ViewFactory  {
  associatedtype View: SwiftUI.View
  func createSomeView() -> View
  func createAnotherView() -> View
}

// Type 'ViewFactoryImpl' does not conform to protocol 'ViewFactory'
class ViewFactoryImpl: ViewFactory {
  func createSomeView() -> some View {
    ViewA()
  }

  func createAnotherView() -> some View {
    ViewA()
  }
}

The closest you can get to that is to use a type alias. It carries semantic meaning but does nothing to obscure the underlying types.

class ViewFactoryImpl: ViewFactory {
  typealias View = ViewA

  func createSomeView() -> View {
    ViewA()
  }

  func createAnotherView() -> View {
    ViewA()
  }
}

CodePudding user response:

The solution you came up with by playing around is exactly what you need

As mentioned elsewhere, the main issue with your first protocol is that you're enforcing createSomeView() createAnotherView() both return the same type. While ViewA() and ViewB() are both candidates for V, since they conform to View they are still different types, and therefore cannot BOTH be V in a given object.

By defining both V1 and V2, you allow for each function to return a different type, or the same type, it's all acceptable. By making both V1 and V2 require View conformance, you allow for the some View syntax

  •  Tags:  
  • Related