I recently launched a Slack app to help with channel bloat! Simply installing it would help me out a bunch. I have 2/10 installations required to submit my app to the Slack Marketplace. Thanks for helping me reach that goal.
I’ve been working on developing an iOS 14 app in my free time lately, and the other day I wanted to create a TextField
to receive input from the user. I needed a number, so I changed the keyboardType
to numberPad
and added some validation logic. Everything was fairly easy to set up especially considering I have never developed on iOS before or written code in objective C. Then came the doozy. Whenever I tapped on something other than the TextField
, nothing happened. I expected the keyboard to go away but it didn’t want to budge. Every app I have ever used had this behavior, so I assumed that it was the built-in default behavior. I was wrong. I went down rabbit hole after rabbit hole trying to figure out how to hide the keyboard. Most of the problems I encountered were due to blog posts and StackOverflow answers referring to earlier versions of iOS, and since I was developing for iOS 14, all of my code and views were written differently. (Again, I have never developed for iOS before. It is very well possible that I am completely wrong and I could have solved this much quicker with any of the other snippets out on the internet.) It turns out that the behavior of hiding a keyboard when a TextField
becomes unfocused is not natively built into Swift. The alternative that I ended up going with was extending View
with a function that sends an action to resignFirstResponder
. Then I added onTapGesture
to a view that encompassed the screen where the keyboard showed up and called the function as a result. The whole process is still a little weird to me, but it has started to make more sense the more I look at it. Here’s an example of the code.
#if canImport(UIKit)
extension View {
func hideKeyboard() -> Void {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
#endif
struct ContentView: View {
@State private var myInput : String = ""
var body: some View {
ScrollView {
TextField("Demo text field", text: $myInput)
.multilineTextAlignment(.center)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.numberPad)
}
.onTapGesture(count: 1, perform: self.hideKeyboard)
}
}
I think the key here for me is that ScrollView
takes up the entire screen of my app, so when I added the listener, if the user tapped anywhere else on the screen, they would experience the desired behavior. Since this is not natively built into Swift, I have to assume that there is no standard way of doing this. Not using this behavior as a default seems like a huge oversight to me, and I wish there was an Apple-approved way of writing in this behavior.