swiftswiftuicombine

How to repeatedly connect a timer with onTapGesture?


As title says I have created a timer to publish every second and on the 5th second it disables a picker in my view. The timer itself is started by tapping on the picker and it works on the first try but doesn't connect on subsequent tries.

I am trying to create one of those web elements that can be dragged across the screen and placed wherever to clear users view but to allow for this I have to disable the picker or else it prevents other gestures from working. What is the problem?

struct ContentView: View {    
    // some other parameters

    @State private var isSorting = false

    let timer = Timer.publish(every: 1, on: .main, in: .common)
    @State private var  count = 0
    
    func timeOut() {
        if count >= 5 {
            isSorting = false
            timer.connect().cancel()
            count = 0
        }
        
        count += 1
    }
    
    var body: some View {
        // other gesture code

        ZStack(alignment: .init(horizontal: .trailing, vertical: .bottom)) {
            TabView {
              // tabs
            }
            
            VStack {
                // spacers
                // if code

                    VStack {
                        Menu {
                           // picker
                        } label: {
                            Image(systemName: "arrow.up.arrow.down")
                        }
                    }
                    .disabled(!isSorting)
                    .onTapGesture {
                        isSorting = true
                        timer.connect()
                    }
                    .onReceive(timer) { _ in
                        timeOut()
                    }
                    // .other modifiers
            }
        }
    }
}

Solution

  • So I figured I could just auto connect and let the function run irrespective of being the tap gesture being triggered. Hopefully this isn't resource wasting. Code below:

    struct ContentView: View {    
        // some other parameters
    
        @State private var isSorting = false
    
        let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
        @State private var  count = 0
        
        func timeOut() {
            if count >= 5 {
                isSorting = false
                count = 0
            }
            
            count += 1
        }
        
        var body: some View {
            // other gesture code
    
            ZStack(alignment: .init(horizontal: .trailing, vertical: .bottom)) {
                TabView {
                  // tabs
                }
                
                VStack {
                    // spacers
                    // if code
    
                        VStack {
                            Menu {
                               // picker
                            } label: {
                                Image(systemName: "arrow.up.arrow.down")
                            }
                        }
                        .disabled(!isSorting)
                        .onTapGesture {
                            isSorting = true
                        }
                        .onReceive(timer) { _ in
                            timeOut()
                        }
                        // .other modifiers
                }
            }
        }
    }