관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] 키보드와 safeArea (#키보드 내려갈때 흔들리는 현상, ignoresSafeArea) 본문

iOS 응용 (SwiftUI)

[iOS - SwiftUI] 키보드와 safeArea (#키보드 내려갈때 흔들리는 현상, ignoresSafeArea)

jake-kim 2025. 1. 21. 01:44

키보드와 safeArea

  • SwiftUI를 사용하면 키보드가 등장할 때 safeArea의 영역이 변경됨
    • 키보드가 올라올 때 별다른 처리가 없어도 키보드가 올라올 때 safeArea가 동적으로 키보드 위로 변하면서 같이 올라가는 것

 

전체 코드) 

struct ContentView: View {
    @State private var text = ""

    var body: some View {
        VStack {
            Spacer()
            Text("safeArea 예제")
                .padding()
            
            TextField("여기에 텍스트를 입력하세요", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
                .background(Color(UIColor.secondarySystemBackground))
                .cornerRadius(8)
                .padding(.horizontal)
            
            Spacer()
        }
    }
}

ignoresSafeArea 개념

  • 위에서 알아본데로 safeArea가 변동되어 뷰들이 올라가기 때문에 UIKit처럼 동작하도록 하려면 ignoreSafeArea를 사용하면 가능
struct ContentView: View {
    @State private var text = ""

    var body: some View {
        VStack {
            Spacer()
            Text("safeArea 예제")
                .padding()
            
            TextField("여기에 텍스트를 입력하세요", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
                .background(Color(UIColor.secondarySystemBackground))
                .cornerRadius(8)
                .padding(.horizontal)
            
            Spacer()
        }
        .ignoresSafeArea(.keyboard, edges: .bottom) // <-
    }
}

ignoreSafe 추가하여 키보드가 올라와도 뷰가 올라가지 않음

 

키보드 내려갈때 흔들리는 현상

  • ScrollView와 같이 TextField를 사용할 때, 스크롤될 때 키보드를 내리고 싶은 경우 보통 아래처럼 DragGesture에서 키보드를 내리는데 이 때 스크롤이 흔들리는 현상이 발생

  • 원인은 키보드가 내려갈 때 시스템 내부적으로 safeArea가 변경되는데 그 때 동시에 스크롤을 처리하면서 메인 스레드 업데이트가 중복되어 흔들리는 것처럼 보이는 것
    • ignoresSafeArea 추가하여 해결이 가능

* scrollView와 키보드 관련 코드)

struct ContentView: View {
    @State private var text = ""
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0) {
                Spacer(minLength: 100)
                
                Text("sample")
                    .font(.headline)
                
                Spacer(minLength: 300)
                
                TextField("input...", text: $text)
                    .font(.largeTitle)
                    .padding(.horizontal, 24)
                
            }
        }
        .ignoresSafeArea(.keyboard, edges: .bottom) // <-
        .simultaneousGesture(
            DragGesture()
                .onChanged { _ in
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

                })
    }
}
Comments