Sergio Bost
Sergio Bost

Reputation: 3209

A Shape that returns multiple options

So what I'm thinking is if there is a way to create a Shape that when initialized can return one of any option that the caller would like. For example:

struct LetterTemplates: Shape {

   init(letterTemplate: LetterTemplate) {
    // This is where I'm confused. Can I somehow select which path to return based on some input           by the caller??

   }

   func path(in rect: CGRect) -> Path { ... } // Short Letter Template
   func path(in rect: CGRect) -> Path { ... } // Long Letter Template
}

Upvotes: 1

Views: 47

Answers (2)

LuLuGaGa
LuLuGaGa

Reputation: 14388

You could try approaching the problem like this: define an enum with possible templates:

enum LetterTemplate {
    case short
    case long
}

Than use that enum to initialise an instance of LetterTemplateShape and use it to choose the right path to draw in path(in:):

struct LetterTemplateShape: Shape {

let letterTemplate: LetterTemplate

init(letterTemplate: LetterTemplate) {
    self.letterTemplate = letterTemplate
    
}

func path(in rect: CGRect) -> Path {
    switch letterTemplate {
    case .short:
        return ShortLetterTemplateShape().path(in: rect)
    case .long:
        return LongLetterTemplateShape().path(in: rect)
    }
}

}

And then declare the actual paths for each case of the enum as separate shapes:

struct ShortLetterTemplateShape: Shape {

    func path(in rect: CGRect) -> Path {
        // actual implementation
    }
}

struct LongLetterTemplateShape: Shape {

    func path(in rect: CGRect) -> Path {
        // actual implementation
    }
}

Upvotes: 1

user652038
user652038

Reputation:

What you're directly asking about is the strategy pattern. To accomplish it in a language with closures, when they need to be forwarded to methods, you do this (with real implementations instead of _ in fatalError()):

struct LetterTemplates: Shape {
  init(letterTemplate: LetterTemplate) {
    switch letterTemplate {
    case .💌:
      path = { _ in fatalError() }
    case .🔠:
      path = { _ in fatalError() }
    }
  }

  private let path: (CGRect) -> Path

  func path(in rect: CGRect) -> Path { path(rect) }
}

However, this is not the SwiftUI way. The SwiftUI way is to have a collection of types that all implement a particular protocol, and then, to use autocomplete with that protocol's name to pick out particular implementations.

People are trying to improve the usability of that.

Upvotes: 1

Related Questions