Ограничьте TextField до x символов с помощью SwiftUI

Используя iOS13.2, Swift-5.1.2, Xcode-11.2, я пробую следующее:

Я хочу использовать TextField. Пользователь может ввести только x-количество символов в текстовое поле.

Мой код выглядит следующим образом:

import Combine
import SwiftUI

class Entry: ObservableObject {

  @Published var entry = "" {
    didSet {
        entry = String(entry.prefix(6)) // trying to limit to 6 characters
    }
  }
}

И в приведенном выше коде уже есть строка исключения.

Я вижу, что didSet{...} неверно (поскольку мы снова и снова попадаем в бесконечный цикл установки / didSetting) ...

Как лучше ограничить TextField x количеством символов?

Вот остальной код:

struct NumberView: View {
    var body: some View {

        Group {
            HStack {
                Spacer()
                NumberIcon(number: 1)
                NumberIcon(number: 2)
                NumberIcon(number: 3)
                NumberIcon(number: 4)
                NumberIcon(number: 5)
                NumberIcon(number: 6)
                Spacer()
            }
         }
    }
}
struct NumberIcon: View {
    @ObservedObject private var entry = Entry()
    var number: Int = 0
    var body: some View {
        TextField(" ", text: $entry.entry, onEditingChanged: { editing in
            print(editing)
            print(self.$entry)
        })
            .padding()
            .foregroundColor(Color.black)
            .background(Color.green)
            .font(.largeTitle)
            .lineLimit(1)
            .cornerRadius(16.0)
            .clipped()
            .keyboardType(.numberPad)
    }
}

struct NumberView_Previews: PreviewProvider {
    static var previews: some View {
        NumberView()
    }
}

Я знаю, что есть возможности оболочки UIKit для использования старых добрых методов делегата shouldChangeCharactersIn из UITextFieldDelegate, но я хотел бы реализовать ограничение символов исключительно с помощью SwiftUI (без кода UIKit). Как я могу это сделать ?


person iKK    schedule 02.11.2019    source источник


Ответы (3)


Самый простой способ добиться этого в SwiftUI - просто отключить TextField при достижении максимального количества символов:

struct LimittedTextField: View {

    @State private var entry = ""

    let characterLimit = 6

    var body: some View {
        TextField("", text: $entry)
            .disabled(entry.count > (characterLimit - 1))
    }
}
person LuLuGaGa    schedule 02.11.2019
comment
Спасибо, LuLuGaGa, мне нравится это решение. Однако при этом клавиатура исчезает. И мое последнее решение ищет способ перейти ко второму TextField, когда пользователь вводит x-количество символов в первое TextField. У меня есть вопрос о stackoverflow на этот счет: ССЫЛКА. Может быть, у вас тоже есть решение этого вопроса - я ценю это! - person iKK; 02.11.2019

Благодаря этому ответу здесь я нашел решение:

Класс Entry можно переписать:

class Entry: ObservableObject {

    let characterLimit = 6   // limiting to 6 characters
    @Published var entry = "" {
        didSet {
            if entry.count > characterLimit && oldValue.count <= characterLimit {
                entry = oldValue
            }
        }
    }
}
person iKK    schedule 02.11.2019

Я написал библиотеку для таких случаев использования:

import DataField

struct ContentView: View {

    @State private var text = ""
    private let characterLimit = 6

    var body: some View {
        DataField("My Field", data: $text) { text in text.count < 6 } 
    }
}
person Marcus Rossel    schedule 16.10.2020