How to execute different actions every time the text gets switched?

Viewed 49

I currently have some simple code that switches some text when an iBeacon gets close to an iOS client:

    var body: some View {
        if detector.lastDistance == .immediate{
            return Text("close!")
                .modifier(BigText())
                .background(Color.green)
                .onAppear(perform: {
                    busStatus(text: "close!");
                    vibrate()
                })
                .edgesIgnoringSafeArea(.all)
        } else if detector.lastDistance == .near{
            return Text("near")
                .modifier(BigText())
                .background(Color.green)
                .onAppear(perform: {
                    busStatus(text: "near!")
                })
                .edgesIgnoringSafeArea(.all)
        } else if detector.lastDistance == .far{
            return Text("far")
                .modifier(BigText())
                .background(Color.green)
                .onAppear(perform: {
                    busStatus(text: "far!")
                })
                .edgesIgnoringSafeArea(.all)
        } else {
            return Text("no data")
                .modifier(BigText())
                .background(Color.red)
                .onAppear(perform: {
                    busStatus(text: "no data!")
                })
                .edgesIgnoringSafeArea(.all)
        }
    }
}

Right now, when I execute the code, "no data!" gets spoken, however, when I move the beacon closer, the text changes and the color goes green, however the busStatus function (text to voice) does not run, neither does my vibrate function.

Is this a design issue with how I am writing this?

1 Answers

Too many duplications... it's really needed to be refactored into separated model type to have something like

@State private var status: CLProximity = .unknown

var body: some View {
    Text(status.text)
        .modifier(BigText())
        .background(status.color)
        .onChange(of: status) {
            busStatus(text: $0.spoken)
            if $0 == .immediate {
               vibrate()
            }
        }
        .edgesIgnoringSafeArea(.all)
}

and new type (with corresponding initializer from underline API)

extension CLProximity {

  var text: String {
    switch self {
      case .immediate:
        return "close!"
      case .near:
        return "near"
      case .far:
        return "far"
      default:
        return "no data"
    }
  }

  var spoken: String {
    switch self {
      case .immediate:
        return "close!"
      case .near:
        return "near!"
      case .far:
        return "far!"
      default:
        return "no data!"
    }
  }

  var color: Color {
    switch self {
      case .immediate, .near, .far:
        return .green
      default:
        return .red
    }
  }
}
Related