SwiftUI - Avoid duplicating code

I have the following code

  var body: some View
  {
  @State private var repeatFrequency = 1
  @State private var period = Period.months

    Form
    {
        // --- several Views (HStack, etc.)

        Toggle("Only Once", isOn: $onlyOnce)
        
        if !onlyOnce
        {
          HStack
          {
            Text("Repeat every")
            Text("\(repeatFrequency)")
            Stepper("", value: $repeatFrequency, in: 1...1000)
              .fixedSize()
          }
          
          Picker("", selection: $period)
          {
            ForEach(periods, id: \.self)
            { period in
              let tagValue = periodCodes[periods.firstIndex(of: period)!]
              Text("\(period)\(repeatFrequency > 1 ? "s" : "")").tag(tagValue)
            }
          }
          .pickerStyle(.segmented)
        }
        
        HStack
        {
          Text(onlyOnce ? "On: " : "Starting: ")
          DatePicker("",
                     selection: $date,
                     in: Date.tomorrow()...,
                     displayedComponents: .date)
          .fixedSize()
        }
      }

The code inside the ‘if’ is duplicated a couple of times in my project. I would like to code this only once, as a View, and be able to include this wherever I need it.

Something like this:

if !onlyOnce
{
  setRecurringView(frequency: repeatFrequency, period: period)
}

I don’t want to go to the view. I want it incorporated into the View where it is.

I hope I’m explaining this clearly.

Thanks in advance.

Hi Peter,

Yeah, kind of.

To paraphrase what you are getting at, is this the code you want to be in the external view that you place within your if statement?

          HStack
          {
            Text("Repeat every")
            Text("\(repeatFrequency)")
            Stepper("", value: $repeatFrequency, in: 1...1000)
              .fixedSize()
          }
          
          Picker("", selection: $period)
          {
            ForEach(periods, id: \.self)
            { period in
              let tagValue = periodCodes[periods.firstIndex(of: period)!]
              Text("\(period)\(repeatFrequency > 1 ? "s" : "")").tag(tagValue)
            }
          }
          .pickerStyle(.segmented)

If so then create a View in which you define the parameters that you are passing in:

This is a total guess but maybe something like this:

import SwiftUI

struct RecurringView: View {
    @Binding var frequency: Int
    @Binding var period: Period
    let periods = ["day", "week", "month", "year"]
    let periodCodes: [Period] = [.days, .weeks, .months, .years]

    var body: some View {
        HStack
        {
            Text("Repeat every")
            Text("\(frequency)")
            Stepper("", value: $frequency, in: 1...1000)
                .fixedSize()
        }

        Picker("", selection: $period)
        {
            ForEach(periods, id: \.self)
            { period in
                let tagValue = periodCodes[periods.firstIndex(of: period)!]
                Text("\(period)\(frequency > 1 ? "s" : "")").tag(tagValue)
            }
        }
        .pickerStyle(.segmented)
    }
}

struct RecurringView_Previews: PreviewProvider {
    static var previews: some View {
        RecurringView(frequency: .constant(1), period: .constant(.months))
    }
}

Yes! That worked. I was so close. I had a value set in the @Binding variables, which Xcode didn’t like. It never occurred to me to leave the initial value out.

Once again, Chris, you saved the day. Thanks.

No worries Pete. Glad it worked for you.