SwiftUI DatePicker issue iOS 17.1
Asked Answered
T

5

15

The code below is working fine in iOS 17.0.1, but in the latest update, 17.1 DatePicker does not open when we tap on it.

After several tries, I found that on the long press, around 2-3 seconds, it opens the date picker.

Any solution for this issue? How do I open only on tap?

VStack(alignment: .leading){
Text("Date".localized())
    .applyFont(style: .Medium, size: 18)
    .foregroundColor(Colors.grayLight)
        HStack{
            let lastYear = Calendar.current.date(byAdding: .year, value: -1, to: Date()) ?? Date()
                if let date = checkLowerBound(){
                    DatePicker("",selection:$selectedDate, in: date...Date(), displayedComponents: [.date])
                        .frame(width: 100)
                    }else{
                    DatePicker("",selection:$selectedDate, in: lowestDate...Date(), displayedComponents: [.date])
                        .frame(width: 100)
                    }
                    Spacer()
                    }
                    .padding(.horizontal, 10)
                }
    .cardProperty()
    .allowsHitTesting(!(eventTransaction != nil && eventTransaction?.by != UserDefaults.userID))
Tarantula answered 27/10, 2023 at 11:5 Comment(10)
Can you show a minimal reproducible code that produces your specific issue, see: minimal code.Phipps
@workingdogsupportUkraine I took the default DatePicker; please check below code DatePicker("",selection: $selectedDate, in: ...Date(), displayedComponents: [.date]).frame(width: 100)Tarantula
show the code you are using, not just one line of it. Your issue is probably due to other factors. Show some code that can be compiled and run to produce your issue. Then others can try to find a solution.Phipps
@workingdogsupportUkraine same line same code is working fine in iOS 17.0.1 with normal tap and after I updated mobile OS to 17.1 normal tap stopped working and on long press same code opened DatePicker so this is the issue of latest OS.Tarantula
Since you don't want to show your code that can be compiled and run to produce your issue, I can only suggest you comment out the allowsHitTesting..., then your custom modifiers (eg cardProperty), one by one to see if that makes a difference.Phipps
@workingdogsupportUkraine I already shared full code, i edit my question where you can find full code which i use for DatePickerTarantula
Got the same issue on UIKit, any updates? Thanks. @HardikThakkarEmilia
No not get any solution. I will update here once I find any solution for the same, also don't know why I am getting minus votes on the real issue.Tarantula
same issue? did you solve it?Simmie
Hi @MetinAtalay No still not get any solution.Tarantula
C
32

It appears that if a TapGesture is handles somewhere higher in the hierarchy, as of 17.1, the DatePicker with displayedComponents: .date will defer to it, and not trigger its own behavior.

simultaneousGesture does not appear to help. However, I found a hacky solution. By wrapping the DatePicker with its own TapGesture handler with a required Count, this buggy behavior will not be triggered as long as the count is not fulfilled.

Minimal viable triggering code with solution:

struct ContentView: View {
@State private var date = Date()

var body: some View {
    VStack {
        DatePicker(
            "Foo",
            selection: $date,
            displayedComponents: .date
        )
        .onTapGesture(count: 99, perform: {
            // overrides tap gesture to fix ios 17.1 bug
        })
    }
    .onTapGesture {
    }
  }
}
Composed answered 8/11, 2023 at 17:19 Comment(3)
In my case, I already had a tap gesture for DatePicker. So I put my gesture next one after (count:99): like .simultaneousGesture(TapGesture().onEnded({ })Unloosen
Hey Roy does this workaround still work? I have tried this way on 17.5 (even on 18.0 beta) but adding tap gesture of count 99 to the date picker still doesn't work.Zonate
@JackStark Still works for me (on iOS 18.0 Simulator). But honestly, looking back, whether this workaround does or does not break, I think it's better to fix the cause than use it to treat the symptom. (is this native date picker functionality exactly what we want? if so, why is our date picker inside another tappable view? if not, isn't there a better way?)Composed
S
5

I encountered a similar issue and found a solution. In my case, the problem arose when I used onTapGesture on the entire ZStack containing my content and called view.endEditing(). This issue occurred in version 17.1 but not in earlier versions.

Septennial answered 3/11, 2023 at 13:59 Comment(1)
People who found this answer helpful, can you please tell me the exact solution?Toffeenosed
H
1

** because I can not add a comment on Sohan and Roy Rodney Answers

the issue is as Sohan said I was using onTapGesure on ZStack to end editing and close the keyboard. and

the solution is as Roy Rodney said to add .onTapGesture(count: 99) after DatePicker

I found solution to add .onTapGesture(count: 99) {} before onTapGesture that ends editing

  .onTapGesture(count: 99) {}
  .onTapGesture {
          UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
   } 
Hearttoheart answered 18/4 at 8:54 Comment(1)
This solution worked for me. I applied this to my DatePicker which was nested within a ZStack that had its own onTapGesture.Stormproof
A
0

The problem caused by another gestureRecogniser somewhere in the view hierarchy, causing either the SwiftUI DatePicker doesn't popup at all or it will not sense touch on the calendar.

So we have to find the problematic one and disable it - when and where we'd like to use the DatePicker - to make it possible that the DatePicker could receive the touch (tap).

If we use SwiftUI only @Roy Rodney's solution could be enough but in UIKit SwiftUI mixed environment it's not enough.

In my case the problem was with a UIViewController - which has an UIHostController for SWiftUI view - with an added gestureRecogniser, as the delegate of that gestureRecogniser and I solved the problem with following delegate method.

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
     shouldReceive touch: UITouch) -> Bool {
        return !(touch.view is UIButton)
}

But even in this case the solution of @Roy Rodney (.onTapGesture(count: 99) {}) is important as the bug remained the problem too in the SwiftUI code.

Anuran answered 8/8 at 21:20 Comment(0)
B
-1
DatePicker(
    "operation_date",
    selection: $operationDate,
    displayedComponents: .date
)
.datePickerStyle(.compact)
.onTapGesture {
// your code to run on tap on DatePicker 
}
.onTapGesture(count: 9) {}
Blythe answered 5/8 at 15:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.