SwiftUI Keyboard Dismiss
어제 구현한 팀 과제를 다시 한 번 구현하던 도중에 추가해보고 싶은 기능이 있었다.
사용자 입력을 소프트 키보드 혹은 버튼을 통해서 입력 받는데, 소프트 키보드로 입력 받은 경우에 Submit을 누르지 않고, 뷰의 클릭하더라도 소프트 키보드가 닫히도록 구현하고 싶었다.
1. Focused
우선 이 기능은 SwiftUI 3.0 (iOS 15) 이상부터 지원한다. 그런 탓인가 정말 간단하게 구현이 가능하다.
var body: some View {
@State private var input: String = ""
@FocusState private var isFocused: Bool
// 생략...
VStack {
TextField("PlaceHolder", $input)
.font(.title)
.focused(isFocused)
}
.onTapGesture {
isFocused = false
}
}
하지만 실제로 사용할 때는 이렇게 단일 뷰에서 활용하지 않는다. 여러 뷰들이 계층 구조를 이루면서 배치되어 있을 것이다.
상태 프로퍼티는 선언된 뷰에서만 접근 가능하므로 자식 뷰에서 접근하기 위해선 @Binding을 사용해야 한다.
struct ParentView: View {
@FocusState private var isFocused: Bool
var body: some View {
VStack {
// 생략
ChildView(isFocused: self.$isFocused) // Binding이므로 $
}
.onTapGesture {
isFocused = false
}
}
}
struct ChildView: View {
@State private var input: String = ""
@Binding var isFocused: Bool
var body: some View {
VStack {
// 생략
TextField("PlaceHolder", $input)
.focused(isFocused)
}
}
}
자식 뷰는 @Binding을 통해 부모 뷰에 있는 상태 프로퍼티에 접근하고 있다.
VStack의 터치하면 TextField의 Focus가 false로 바뀌면서 소프트 키보드는 내려가게 될 것이다.
하지만 이 코드는 컴파일 에러가 발생한다.
보아하니 타입의 문제인 것 같다. 타입을 FocusState<Bool>.Binding 으로 설정해주면 컴파일이 정상적으로 진행된다.
struct ParentView: View {
@FocusState private var isFocused: Bool
var body: some View {
VStack {
// 생략
ChildView(isFocused: isFocused) // Binding이므로 $
}
.onTapGesture {
isFocused = false
}
}
}
struct ChildView: View {
@State private var input: String = ""
// @Binding -> FocusState<Bool>.Binding
var isFocused: FocusState<Bool>.Binding
var body: some View {
VStack {
// 생략
TextField("PlaceHolder", $input)
.focused(isFocused)
}
}
}
'💻 개발 > iOS' 카테고리의 다른 글
[iOS / Swift] Swift 문자열 정복하기 (aka 'Character') (0) | 2022.11.03 |
---|---|
[iOS / SwiftUI] 다양한 상태 프로퍼티들을 알아보자! (0) | 2022.10.24 |
[iOS / SwiftUI] ForEach로 View를 리펙토링 해볼까요? (0) | 2022.10.11 |
[iOS / Swift] lim 클로저 -> 0 (클로저, 극한으로 줄여보기) (0) | 2022.10.05 |
[iOS / Swift] 클로저와 프로퍼티, 가볍게 알아보기 (0) | 2022.10.02 |