Published on

SwiftUI-da TextField'dan qanday foydalanish kerak

Authors

Hammaga salom, xush kelibsiz! Men — Nik, va biz bootcamp kursining, deylik, so'nggi bosqichidamiz — keyingi bir qancha video ancha oson bo'ladi, chunki ular SwiftUI ilovalarimizga qo'shadigan eng keng tarqalgan, asosiy komponentlarni ko'rib chiqamiz, xolos. Agar siz shu kungacha mavzuni kuzatib kelayotgan bo'lsangiz, sizga albatta rahmat aytmoqchiman, va umid qilamanki, sizlar biror narsa o'rganmoqdasiz — biz ushbu kursda haqiqatan ham barcha asosiy narsalarni qamrab olmoqdamiz.

Ushbu videoda esa biz text fieldlarni ko'rib chiqamiz. Bu, foydalanuvchingiz biror narsa yozishi kerak bo'lgan vaziyatlar uchun ekranga qo'yish uchun mukammal komponent: biz ekranga text field qo'yamiz, foydalanuvchi unga matn yozadi, va biz shu yozilgan qiymatdan ilovamizning boshqa joyida foydalanishimiz mumkin. Buni amalga oshirish ancha oson, shuning uchun bu qisqa video bo'ladi, ammo men sizlarga buni chiroyli ko'rinishga keltirishning bir nechta tezkor usulini ham ko'rsataman.


Yangi loyiha fayli yaratish

Har doimgidek, shu video uchun yangi fayl yaratishdan boshlaymiz: Navigator'da o'ng tugmani bosib, yangi fayl yaratamiz — bu SwiftUI View bo'ladi, va biz text field'lar haqida gaplashayotganimiz uchun buni TextFieldBootcamp deb ataymiz. "Create" tugmasini bosamiz, ichkariga kirgach esa canvas'da "Resume" tugmasini bosib, kod yozishni boshlaymiz.

SwiftUI ekranga text field qo'shishni juda-juda osonlashtiradi — shunday qilib foydalanuvchilar ma'lum bir ma'lumotni kiritib yozishi mumkin bo'ladi.


Oddiy TextField qo'shish

Avval juda sodda tarzda boshlaylik: TextField deb yozib, qavslarni ochamiz — bu yerda juda ko'p turli variant bor, ammo biz sodda yo'l tutamiz va string protokoli va binding textga ega bo'lgan variantdan foydalanamiz. Title — bu text field'da hech qanday matn bo'lmaganda ko'rinadigan placeholder (o'rin tutuvchi matn), shuning uchun bu yerga, masalan, "Type something..." deb yozamiz.

Text uchun esa bizga binding string kerak — shuning uchun yuqorida @State var textFieldText, turi String, qiymati esa hozircha bo'sh string bo'lgan o'zgaruvchi yaratamiz, va buni dollar belgisi bilan text field'ga bog'laymiz: $textFieldText:

@State var textFieldText: String = ""

var body: some View {
    TextField("Type something...", text: $textFieldText)
}

Canvas'da "Resume" tugmasini bossak, standart fon oq rangda bo'lgani uchun buni biroz ko'rish qiyin, ammo ekranda haqiqatan ham bizning text field'imiz bor. Live Preview'da "Play" tugmasini bossak, shu text field ustiga bosib, yoza boshlashimiz mumkin (haqiqiy ilovada, albatta, klaviatura avtomatik chiqib keladi, ammo simulyatorda klaviatura yo'q, shuning uchun shunchaki kompyuter klaviaturasidan foydalanamiz). Demak, bu — foydalanuvchiga biror narsaga matn qo'shish imkonini berishning juda sodda usuli.


TextField'ni moslashtirish

Keling, buni biroz oldinga olib borib, formatlash va qo'shimcha mantiq qo'shib, bu text field'ni biroz realroq qilaylik.

Avval text field'ni formatlaymiz — buning uchun textFieldStyle bor: default va plain variantlari hozirgi ko'rinishga juda o'xshash, roundedBorder esa chetiga ingichka chiziq (border) qo'shadi. Buni tezda sinab ko'raylik — ammo shaxsan men bu standart uslublardan foydalanmayman, text field'ni to'g'ridan-to'g'ri moslashtirishni afzal ko'raman, shuning uchun buni izohga olib qo'yamiz — sizga shunchaki bunday narsa mavjudligini bilishingiz uchun ko'rsatdim.

Endi fon (background) qo'shamiz: Color.gray, ammo bu rang juda qorong'i bo'lib chiqadi, shuning uchun unga, masalan, 0.3 qiymatida opacity (shaffoflik) qo'shamiz — bu ancha yaxshi ko'rinadi. Chetlariga biroz padding qo'shamiz (fondan oldin), fonga esa burchaklarini yumaloqlashtirish uchun cornerRadius(10) qo'shamiz.

Endi shu text field'ga matn yozishni boshlaganimizda, matnning rangini o'zgartirmoqchiman — buni foregroundColor orqali amalga oshiramiz: .red, shunchaki ko'zga yaqqol ko'rinishi uchun. Shriftni ham o'zgartirishimiz mumkin — .font(.headline). Endi "Type something..." deb yozilgan joyga "hello" deb yozsak, bu matn qizil rangda va headline shriftida ko'rinadi (placeholder matnining rangini, ya'ni shu qorong'i kulrang rangni o'zgartirishning oson yo'lini topa olmadim, shuning uchun hozircha shu holicha qoldiramiz):

TextField("Type something...", text: $textFieldText)
    .padding()
    .background(
        Color.gray
            .opacity(0.3)
            .cornerRadius(10)
    )
    .foregroundColor(.red)
    .font(.headline)

Save tugmasini qo'shish va uni formatlash

Keling, ekranimizni yakunlaylik. Shu text field'ni VStack ichiga joylaymiz, va Button qo'shamiz — action va labelga ega variantdan foydalanamiz, harakat uchun esa hozircha bo'sh qoldiramiz. Matn uchun esa, masalan, "save"ni katta harflarga o'zgartirib (.uppercased()) yozamiz, shunda u "SAVE" bo'lib chiqadi.

Keling, buni ham biroz formatlay: text field uchun ishlatgan formatlashni (padding, fon rangi, foreground rangi, shrift) nusxalab, shu yerga joylaymiz. Faqat bir nechta o'zgartirish kiritamiz: kulrang o'rniga endi Color.blue ishlatamiz, opacity'ni olib tashlaymiz, foreground rangini esa oq qilamiz. Bundan tashqari, bu fonning text field kabi imkon qadar keng bo'lishini xohlayman — text field'da bu standart bo'yicha shunday bo'ladi (maksimal kengligi cheksiz), ammo tugmaga buni qo'lda qo'shishimiz kerak: fondan oldin .frame(maxWidth: .infinity) qo'shamiz:

Button(action: {

}, label: {
    Text("save".uppercased())
        .font(.headline)
        .foregroundColor(.white)
        .frame(maxWidth: .infinity)
        .padding()
        .background(
            Color.blue
                .cornerRadius(10)
        )
})

Endi shu VStackni NavigationView ichiga joylaymiz — NavigationView deb yozib, qavslarni ochamiz, va mavjud VStackni qirqib olib, shu yerga joylaymiz. Endi nav view ichida bo'lganimiz sababli, sarlavha ham qo'shishimiz mumkin: VStackning pastiga .navigationTitle("Text Field Bootcamp") qo'shamiz.

Mazmunni yuqoriga itarib qo'yish uchun, tugmaning ostiga Spacer qo'shamiz, va butun VStack atrofiga ozgina padding qo'shamiz — bu ko'rinishni biroz yaxshilaydi:

NavigationView {
    VStack {
        TextField("Type something...", text: $textFieldText)
            .padding()
            .background(
                Color.gray
                    .opacity(0.3)
                    .cornerRadius(10)
            )
            .foregroundColor(.red)
            .font(.headline)

        Button(action: {

        }, label: {
            Text("save".uppercased())
                .font(.headline)
                .foregroundColor(.white)
                .frame(maxWidth: .infinity)
                .padding()
                .background(
                    Color.blue
                        .cornerRadius(10)
                )
        })

        Spacer()
    }
    .padding()
    .navigationTitle("Text Field Bootcamp")
}

Matnni saqlash mantig'i

Endi haqiqiy text field'imizga mantiq qo'sha boshlaylik — shunday qilib, masalan, "hello" deb yozib, "Save" tugmasini bossak, bu haqiqatan ham saqlanadi.

Avval matnni saqlash uchun funksiya yaratamiz: bodydan tashqarida, pastda, func saveText() deb yozamiz, qavslarini ochib-yopamiz. Matnni saqlaganimizda u bilan nima qilamiz? Keling, buni mahalliy massivga qo'shaylik (append). Shuning uchun yuqorida ma'lumotlar massivi yaratamiz: @State var dataArray, turi — [String], hozircha bo'sh massivga tenglashtiramiz.

saveText funksiyasi ichida dataArray.append(...)ni chaqiramiz — yangi element nima bo'ladi? Bu bizning textFieldText o'zgaruvchimiz bo'ladi, chunki esda tutamiz: bu o'zgaruvchi text field'ga bog'langan, shuning uchun text field'ga nima yozilsa, bu o'zgaruvchi ham real vaqtda aynan shunga teng bo'lib turadi:

@State var dataArray: [String] = []

func saveText() {
    dataArray.append(textFieldText)
}

Saqlangan ma'lumotlarni ro'yxat sifatida ko'rsatish

Keling, shu tugmaning ostiga tezkor bir ForEach qo'shib, dataArray ichidagi barcha ma'lumotni ko'rsataylik. ForEach deb yozamiz, va bu safar id parametriga ega bo'lgan variantdan foydalanamiz: ma'lumot, albatta, bizning dataArrayimiz, id uchun esa \.selfni beramiz — bu, asosan, massivdagi har bir element uchun o'z-o'zidan bir identifikator yaratadi. Tarkib uchun esa, har bir elementni data deb ataymiz, va shunchaki shu dataga ega bo'lgan Text qo'shamiz:

ForEach(dataArray, id: \.self) { data in
    Text(data)
}

Endi bizga qolgan yagona narsa — shu Button ichida saveText() funksiyasini chaqirish:

Button(action: {
    saveText()
}, label: {
    Text("save".uppercased())
        .font(.headline)
        .foregroundColor(.white)
        .frame(maxWidth: .infinity)
        .padding()
        .background(
            Color.blue
                .cornerRadius(10)
        )
})

Canvas'da "Resume" tugmasini bosib sinab ko'raylik: "hello" deb yozib, "Save"ni bossak, bu matn dataArrayga qo'shilishi va tugmaning ostida ko'rinishi kerak. Bosamiz — va haqiqatan ham "hello" pastda paydo bo'ladi, demak matnimiz saqlandi. Agar matnni "hello there"ga o'zgartirib, yana "Save"ni bossak, ro'yxat yangilanganini ko'ramiz.

Bu yerda alohida ta'kidlamoqchi bo'lgan bir narsa bor: "Save"ni bosgandan keyin, matn hamon text field'da turib qoladi. Odatda esa, foydalanuvchi biror narsani saqlagandan keyin, bu matn ekran-dan g'oyib bo'lishi kerak, chunki ma'lumot allaqachon saqlangan — aks holda, foydalanuvchi "Save"ni bir necha marta bosib, bir xil matnni bir necha marta saqlab qo'yishi mumkin. Buning oldini olish uchun, saveText funksiyasida, matnni dataArrayga qo'shgandan so'ng, textFieldTextni yana bo'sh string'ga qaytaramiz:

func saveText() {
    dataArray.append(textFieldText)
    textFieldText = ""
}

Sinab ko'raylik: "hello" deb yozib, "Save"ni bossak, "hello" saqlanadi, va text field yana bo'sh bo'lib qoladi. Yana bir bor sinab ko'rsak, xuddi shunday ishlaydi.


Matnni tekshirish (validatsiya)

Videoni yakunlashdan oldin, sizlarga yana bir juda foydali usulni ko'rsatmoqchiman: matnni tekshirish (validate qilish). Ba'zan siz, masalan, matnda haqorat so'zlar bo'lmasligiga, yoki kamida uch-besh harf bo'lishiga ishonch hosil qilishni xohlaysiz — masalan, agar bu foydalanuvchi nomi bo'lsa, foydalanuvchining faqat bitta harf kiritishini xohlamaysiz, balki kamida olti harf yoki maxsus belgi bo'lishini talab qilishni xohlashingiz mumkin.

Shuning uchun yana bir funksiya qo'shamiz — saveTextdan oldin, func textIsAppropriate() deb yozamiz, bu funksiya Bool qaytaradi. Ichida esa, shunchaki matn mos keladigan yoki kelmaydigan ekanligini tekshiramiz — agar yaxshi bo'lsa, true qaytaramiz, yomon bo'lsa — false. Haqiqiy ilovada, albatta, bu yerda ko'proq mantiq bo'lardi, ammo hozircha shunchaki matnning kamida uch belgidan iborat ekanligini tekshiramiz: agar textFieldText.count qiymati 3dan katta yoki teng bo'lsa, true qaytaramiz, aks holda — false:

func textIsAppropriate() -> Bool {
    if textFieldText.count >= 3 {
        return true
    }

    return false
}

Endi shu textIsAppropriate() funksiyasidan body'da foydalanishimiz mumkin: saveText()ni chaqirishdan oldin, if textIsAppropriate() deb tekshiramiz (eslatib o'tay: bu Bool qaytaradi) — agar bu true bo'lsa, saveText()ni chaqiramiz:

Button(action: {
    if textIsAppropriate() {
        saveText()
    }
}, label: {
    Text("save".uppercased())
        .font(.headline)
        .foregroundColor(.white)
        .frame(maxWidth: .infinity)
        .padding()
        .background(
            Color.blue
                .cornerRadius(10)
        )
})

Tezda sinab ko'raylik: ikki harf — "hi" — yozib, "Save"ni bossak, bu ishlamaydi. Ammo uch harf yozib bossak, endi saqlanadi — demak, bu ishlayapti.


Save tugmasini shartli ravishda faollashtirish

Keling, buni bir necha qadam oldinga olib boraylik — endi shu tugmani matn mos kelganda ko'k, mos kelmaganda esa boshqa rangda qilamiz. Avval cornerRadiusni fondan keyinga ko'chiramiz, so'ngra shunchaki Color.blueni chaqirish o'rniga, ternary operatordan foydalanamiz: agar textIsAppropriate() true bo'lsa — Color.blue, aks holda — Color.gray. Bu, asosan, oldingi bir videoda batafsil ko'rib chiqgan ternary operatorimiz — agar matn mos kelsa, ko'k, aks holda kulrang:

.background(
    (textIsAppropriate() ? Color.blue : Color.gray)
        .cornerRadius(10)
)

Endi preview'da ko'rishimiz mumkin: foydalanuvchi yozayotganda, ikki harf kiritsa, tugma kulrang bo'lib turadi; yana bir harf qo'shsa — ko'k bo'lib qoladi. Bu, "Save" tugmasini qachon bosish mumkinligini ko'rsatuvchi juda qulay belgi bo'lib xizmat qiladi.

Buni yanada bir qadam oldinga olib borishimiz mumkin: matn mos kelmaganda, tugmaning o'zini ham o'chirib (disable) qo'yishimiz mumkin. Tugmaning o'ziga .disabled(...) qo'shamiz — bu Boolean qabul qiladi. Tugma qachon o'chirilgan bo'lishi kerak? Matn mos kelmaganda — shuning uchun undov belgisi (!) yordamida textIsAppropriate()ning teskarisini olamiz: matn mos kelganda bu false (demak, o'chirilmagan), mos kelmaganda esa true (demak, o'chirilgan) bo'ladi:

Button(action: {
    if textIsAppropriate() {
        saveText()
    }
}, label: {
    Text("save".uppercased())
        .font(.headline)
        .foregroundColor(.white)
        .frame(maxWidth: .infinity)
        .padding()
        .background(
            (textIsAppropriate() ? Color.blue : Color.gray)
                .cornerRadius(10)
        )
})
.disabled(!textIsAppropriate())

Yana sinab ko'raylik: ilovamizda tugmani bosishga harakat qilsak, u hatto bosilmaydi ham, chunki o'chirilgan. Ammo uch harf yozsak, endi bosish mumkin bo'ladi, va matnimizni saqlay olamiz.


Xulosa

Mana shu — ushbu video uchun shu, xolos. Endi siz text field'dan qanday foydalanishni bilasiz. Ketishdan oldin shuni ham aytib o'taman: text field yaratganimizda, qavslarni ochganimizda, bir qancha turli variant bor edi, va biz eng sodda variantdan foydalandik. Ammo agar foydalanuvchi text field'ni bosgan paytda biror harakat ishga tushishini xohlasangiz, onEditingChanged completion'idan foydalanishingiz mumkin; agar foydalanuvchi klaviaturadagi "Return" (pastki o'ng) tugmasini bosganda biror harakat ishga tushishini xohlasangiz esa, onCommit funksiyasidan foydalanishingiz mumkin.

Shuningdek, matnni ma'lum bir ko'rinishda formatlash usuli ham bor — masalan, agar valyuta uchun dollar belgisi raqamlardan oldin chiqishini xohlasangiz, formatterlardan foydalanishingiz mumkin. Bular biroz murakkabroq va kamroq ishlatiladi, shuning uchun men ularni ushbu boshlang'ich kursda batafsil ko'rib chiqmayman, ammo ularning mavjudligini bilib qo'yishingiz kerak.

Demak, text field'lar juda sodda va ulanishi oson — SwiftUI foydalanuvchilaringizga matn yozib, ilovangizga jo'natish imkonini beradi. Bu foydalanuvchi nomlari yoki izohlarni qo'shish uchun, va deyarli har qanday boshqa joyda, kishi haqiqatan ham biror narsa yozishi kerak bo'lganda juda qulay. Va ha, agar bilmoqchi bo'lsangiz: text field bitta qator bilan cheklangan — bizda text field'da bir nechta qatorga ega bo'lish imkoni yo'q, bu shunchaki bitta qatorli maydon, xolos. Agar bir nechta qator kerak bo'lsa, TextEditordan foydalanishimiz mumkin — va ajablanarlisi shu, keyingi videoda aynan shuni qilamiz.

Har doimgidek, tomosha qilganingiz uchun rahmat — agar biror narsa o'rgangan bo'lsangiz, layk tugmasini bosing, va agar bu kontentdan zavqlanayotgan bo'lsangiz, obuna bo'lish tugmasini bosing. Men — Nik, bu Swiftful Thinking, keyingi videoda ko'rishamiz!

Buy mea coffee