해당 글에서는 SwiftUI 환경에서 TextField, TextEditor, Button에 포커싱을 하는 방법에 대해서 공유합니다.
0) 개발 환경
구분
구분 종류
버전
언어
Swift
5.7.2
개발 환경
IOS
16.2
UI Interface
SwiftUI
개발 도구
XCode
14.2
1) TextField의 포커싱 방법
💡 @FocusState 속성은 iOS 15 이상 버전에서 사용이 가능하며, TextField, TextEditor, Button에 대해서 포커싱이 생기도록 하는 기능을 제공합니다.
1. struct 내에 변수로 @FocusState를 구성합니다.
💡 struct 영역 내에 enum을 구성하고 @FocusState의 타입을 해당 enum으로 지정합니다.
struct ContentView: View {
enum FocusableField: Hashable {
case userId
case roomNo
}
@FocusState var focusField: FocusableField?
}
2. TextField를 구성합니다.
💡 해당 부분에서 TextField 영역의 focused() 부분에 주목을 해야 합니다. 첫 번째 파라미터는 $focusField를 두 개의 TextField 영역에 동일하게 적용이 되어 있고, 두 번째 파라미터는 각각 enum으로 구성한 값을 참조하고 있습니다. 그래서 동일한 Focus가 발생하였을 경우 .userId 나. roomId로 구분자를 두었습니다.
struct ContentView: View {
enum FocusableField: Hashable {
case userId
case roomNo
}
@State private var userId: String = "" // 사용자 아이디
@State private var roomNo: String = "" // 방 번호
@FocusState var focusField: FocusableField?
var body: some View {
// 해당 부분으로 감싸서 구성합니다.
NavigationView{
VStack {
// 사용자 아이디 영역
TextField("사용자 아이디를 입력해주세요.", text: self.$userId)
.background(Color("#E1E1E1"))
.textFieldStyle(.roundedBorder)
.focused($focusField, equals: .userId)
.keyboardType(.default)
.padding()
// 방 번호 영역
TextField("방 번호를 입력해주세요.", text: self.$roomNo)
.background(Color("#E1E1E1"))
.focused($focusField, equals: .roomNo)
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.padding()
}
.padding()
}
}
3. “버튼”을 선택 할 경우 데이터가 존재하지 않는 경우 유효성 검증을 수행하고 메시지가 출력되도록 구성합니다.
💡 Button을 누를 경우, onTouchEntrance() 함수가 수행이 됩니다. 해당 함수 내에서 @State로 각각 바인딩해둔 값이 존재하지 않는 경우 Text로 메시지를 출력하도록 구성하였습니다.
/**
* ContentView.swift
* Created by Lee on 2023/02/22.
*/
import SwiftUI
struct ContentView: View {
enum FocusableField: Hashable {
case userId
case roomNo
}
@State private var userId: String = "" // 사용자 아이디
@State private var roomNo: String = "" // 방 번호
@State private var validMsg : String = ""
@FocusState var focusField: FocusableField?
var body: some View {
// 해당 부분으로 감싸서 구성합니다.
NavigationView{
VStack {
// 메인 아이콘
Image("swift_icon")
.resizable()
.frame(width: 200, height: 80)
.padding()
// 사용자 아이디 영역
TextField("사용자 아이디를 입력해주세요.", text: self.$userId)
.background(Color("#E1E1E1"))
.textFieldStyle(.roundedBorder)
.focused($focusField, equals: .userId)
.keyboardType(.default)
.padding()
// 방 번호 영역
TextField("방 번호를 입력해주세요.", text: self.$roomNo)
.background(Color("#E1E1E1"))
.focused($focusField, equals: .roomNo)
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.padding()
// 입장 버튼 영역
Button(action: {
onTouchEntrance() // 입장 버튼을 눌렀을 경우 수행되는 함수
}, label: {
Text("입장")
})
.frame(width: 350, height: 20)
.foregroundColor(Color.white)
.padding()
.background(Color("#243062"))
.cornerRadius(10)
// 유효성 메시지 영역
Text(validMsg).padding()
}
.padding()
}
}
/**
* 입장 버튼을 눌렀을 경우 수행되는 함수
*/
func onTouchEntrance(){
print("onTouchEntrance Load")
if userId.isEmpty{
focusField = .userId
validMsg = "사용자 아이디를 입력해주세요." // Validation Message
return
}
else if roomNo.isEmpty {
focusField = .roomNo
validMsg = "방 번호를 입력해주세요." // Validation Message
return
} else{
focusField = nil
validMsg = "" // Validation Message
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}