[SwiftUI] FocusState loses focus

Kihyun Lee·2022년 10월 20일
0

SwiftUI

목록 보기
2/5

Problem


원했던 결과물은 위와 같다. 안 보이던 TextField 를 보이게 함과 동시에 focus 되게 하여 키보드가 올라오도록 하는 것이다.


그러나 앱에서는 테스트와 다르게 위와 같은 상황이 펼쳐졌다.

Why?

@FocusState 가 iOS15 에서 도입된 개념이다보니 버그가 꽤 있는 것 같지만 자료는 많이 없다. 그래서 여러 테스트를 혼자 해보면서 문제를 일으키는 위치는 찾을 수 있었다. NavigationView 와 FocusState 와 if 에 있다.

Code

잘 작동하는 테스트 코드는 아래와 같다. 간단하게 TextField 가 appear 됨과 동시에 focus 해주는 것이다.

import SwiftUI


struct ContentView: View {
    @State private var str = ""
    @State private var show = false
    @FocusState private var focus: Bool

    var body: some View {
//        NavigationView {
            VStack {
                if show {
                    TextField("test", text: $str)
                        .focused($focus)
                }
                Button("show & focus") {
                    show.toggle()
                    focus.toggle()
                }
            }
//        }
    }
    
}

그런데 여기서 주석을 풀고 VStack 을 NavigationView 안에 들어가도록 넣으면 focus 가 풀리는 문제가 생긴다. @State 변수 show 가 바뀌고 computed 프로퍼티인 body 가 다시 그려지면서 NavigationView 가 focus 를 빼앗는 게 아닌가 하는 추측을 하고 있다.

Solution

NavigationView 를 안 쓰면 그만이지만 앱 NavigationView 안에서 NavigationLink 를 쓰고 있어서 NavigationView 를 버릴 수 없었다. 그래서 Opacity 를 써 버렸다. if 는 뷰가 없는 상태에서 appear 되는 것이지만 opacity 는 눈에만 안보이고 사실은 뷰가 있는 상태이다. 이렇게 하면 NavigationView 안에 있어도 focus 가 풀리지 않는다.

import SwiftUI


struct ContentView: View {
    @State private var str = ""
    @State private var show = false
    @FocusState private var focus: Bool

    var body: some View {
        NavigationView {
            VStack {
                TextField("test", text: $str)
                    .focused($focus)
                    .opacity(show ? 1 : 0)
                
                Button("show & focus") {
                    show.toggle()
                    focus.toggle()
                }
            }
        }
    }
    
}

Done

텍스트 필드가 포커스 되어 있는가 상태를 체크하기 위해 @FocusState 대신 iOS14 이하까지 쓰던 UITextFieldDelegate 를 사용할 수도 있긴 하다. 다만 꽤나 번거로운 작업이라 @FocusState 를 자주 쓰는 중이다.

profile
실패도 배우는 게 있으면 성공이다.

0개의 댓글