💫 SwiftUI의 TextField의 사용
우리가 보통 사용하는 SwiftUI의 TextField컴포넌트를 사용하는 방법
import SwiftUI
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack {
Text("Text: \(text)")
.frame(maxWidth: .infinity, alignment: .leading)
TextField("TextField", text: $text)
}
}
}
SwiftUI의 기본 제공 TextField는 쓰기에는 무난하지만 여러 delegate를 사용해 커스텀 해야하는 상황이 오면 결국 UITextField를 커스텀 해 사용하는 경우가 있다.
이 방법은 TextField뿐 아니라 대부분의 UIKit의 컴포넌트들을 비슷한 방법으로 커스텀하여 사용할 수 있다.
💫 UITextField를 SwiftUI의 컴포넌트로 커스텀하기
import SwiftUI
// MARK: - TextFieldRepresentable
struct TextFieldRepresentable: UIViewRepresentable { // 1️⃣
private let placeholder: String
@Binding var text: String
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeUIView(context: Context) -> UITextField { // 2️⃣
let textField = UITextField()
textField.placeholder = placeholder
textField.text = text
textField.delegate = context.coordinator // 3️⃣
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) { // 4️⃣
uiView.text = text
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
}
func makeCoordinator() -> Coordinator { // 5️⃣
Coordinator(text: $text)
}
class Coordinator: NSObject { // 6️⃣
@Binding var text: String
init(text: Binding<String>) {
self._text = text
}
}
}
extension TextFieldRepresentable.Coordinator: UITextFieldDelegate { // 7️⃣
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentValue = textField.text as NSString? {
let newValue = currentValue.replacingCharacters(in: range, with: string)
self.text = newValue
}
return true
}
}
1️⃣ : UIKit의 컴포넌트는 UIViewRepresentable 프로토콜을 채택해 구현할 수 있다.
2️⃣ : UIViewRepresentable의 필수 구현 메소드, 생성할 뷰를 리턴하는 부분으로 이니셜라이징할 코드를 작성하면 된다.
3️⃣ : UITextField에 6️⃣에서 구현한 클래스의 delegate를 주입
4️⃣ : UIViewRepresentable의 필수 구현 메소드, 뷰가 업데이트 될 때마다 실행되는 부분
5️⃣ : UIViewRepresentable의 옵셔널 메소드로 6️⃣에서 구현한 클래스를 생성한다.
6️⃣ : 이 구조체에서 사용할 Coordinator를 구현해준다.
7️⃣ : Coordinator에 커스텀할 delegate를 주입하여 사용하면 된다.
💫 최종코드 및 비교영상
import SwiftUI
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack {
Text("Text: \(text)")
.frame(maxWidth: .infinity, alignment: .leading)
TextField("TextField", text: $text)
TextFieldRepresentable("TextFieldRepresentable", text: $text)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
// MARK: - TextFieldRepresentable
struct TextFieldRepresentable: UIViewRepresentable {
private let placeholder: String
@Binding var text: String
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.placeholder = placeholder
textField.text = text
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
}
func makeCoordinator() -> Coordinator {
Coordinator(text: $text)
}
class Coordinator: NSObject {
@Binding var text: String
init(text: Binding<String>) {
self._text = text
}
}
}
extension TextFieldRepresentable.Coordinator: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentValue = textField.text as NSString? {
let newValue = currentValue.replacingCharacters(in: range, with: string)
self.text = newValue
}
return true
}
}
'iOS > SwiftUI' 카테고리의 다른 글
SwiftUI로 Countdown Timer 만들어보기 (0) | 2022.06.17 |
---|---|
SwiftUI 그라데이션 텍스트 구현하기 (0) | 2022.04.27 |
SwiftUI와 상태관리 (0) | 2022.04.03 |
SwiftUI에서 스켈레톤 UI 적용하기 (0) | 2022.02.20 |
[SwiftUI] EnvironmentObject / ObservedObject / StateObject (0) | 2022.01.30 |