Published on

SwiftUIda UIKit elementlaridan foydalanish (UIViewRepresentable)

Authors

Nega bizga UIKit kerak bo'lib qoladi?

SwiftUI juda zo'r va zamonaviy freymvork. Lekin u atigi bir necha yil oldin yaratilgan. Undan oldingi barcha iOS dasturlar UIKit yordamida yozilgan. Ba'zi eski, lekin o'ta muhim komponentlar (masalan UITextField, MKMapView kabi) SwiftUIdagi muqobillariga qaraganda ancha ko'p imkoniyatlarga ega.

Masalan: SwiftUIdagi oddiy TextField ning ichidagi "Placeholder" (Bo'sh holatdagi kulrang yozuv) rangini to'g'ridan-to'g'ri qizil rangga o'zgartirish qiyin. Lekin UIKit dagi UITextField da buni bemalol qilish mumkin. Shu sababli biz UIKit elementini SwiftUIga o'rab olib kiramiz!

1. Asosiy protokol: UIViewRepresentable

Har qanday UIKit elementini SwiftUIga o'tkazish uchun UIViewRepresentable protokolidan foydalaniladi. U asosan 2 ta funksiyani talab qiladi:

  1. makeUIView - Elementni yaratish (Birinchi marta ekranga chiqqanda ishlaydi).
  2. updateUIView - Elementni yangilash (SwiftUIdagi o'zgaruvchilar o'zgarganda ishlaydi).

Eng oddiy misol

import SwiftUI

struct BasicUIViewRepresentable: UIViewRepresentable {

    // 1. Obyektni yaratamiz
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }

    // 2. SwiftUIdagi o'zgarishlar paytida nima qilish kerakligini yozamiz
    func updateUIView(_ uiView: UIView, context: Context) {
        // Hozircha bo'sh
    }
}

Bu View ni ekranga xuddi boshqa SwiftUI view'lari kabi qo'shish mumkin: BasicUIViewRepresentable().

2. UITextField ni o'rash (Custom Placeholder bilan)

Keling endi kattaroq narsa yasaymiz. Bizga shunday TextField kerakki, uning placeholder'i va uning rangi o'zgartirilishi mumkin bo'lsin:

struct CustomUITextField: UIViewRepresentable {
    @Binding var text: String
    var placeholder: String
    var placeholderColor: UIColor

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)

        // Placeholder uchun qizil rangli Atribut yozamiz
        let attributedPlaceholder = NSAttributedString(
            string: placeholder,
            attributes: [
                .foregroundColor: placeholderColor
            ]
        )

        textField.attributedPlaceholder = attributedPlaceholder

        return textField
    }

    // SwiftUI -> UIKit ga o'tkazish (Tepadan kelgan text o'zgarsa)
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
}

3. Coordinator (Ma'lumotni UIKit'dan SwiftUIga qaytarish)

Yuqoridagi kod bilan biz SwiftUIdan UIKit ga yozuvni jo'nata olamiz (updateUIView orqali). Lekin UIKit da (ya'ni klaviaturada) yozilgan narsa SwiftUIga qaytishi kerak-ku!

Buning uchun biz Coordinator (Vositachi) degan maxsus Class yaratishimiz kerak. U UIKit ning Delegate metodlarini eshitib turadi va qiymatni @Binding o'zgaruvchisiga uzatadi.

Kodni to'liq shaklda yozamiz:

struct CustomUITextField: UIViewRepresentable {
    @Binding var text: String
    var placeholder: String
    var placeholderColor: UIColor

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)
        let attributedPlaceholder = NSAttributedString(
            string: placeholder,
            attributes: [.foregroundColor: placeholderColor]
        )
        textField.attributedPlaceholder = attributedPlaceholder

        // 3. Delegate'ni Coordinator'ga ulaymiz!
        textField.delegate = context.coordinator

        return textField
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }

    // 1. Coordinator yaratish funksiyasi
    func makeCoordinator() -> Coordinator {
        return Coordinator(text: $text)
    }

    // 2. Vositachi Class'ning o'zi
    class Coordinator: NSObject, UITextFieldDelegate {
        @Binding var text: String

        init(text: Binding<String>) {
            self._text = text
        }

        // Har safar foydalanuvchi klaviaturada yozganda ishlaydigan funksiya
        func textFieldDidChangeSelection(_ textField: UITextField) {
            text = textField.text ?? "" // UIKit dagi matnni SwiftUIdagi @Binding ga tenglaymiz!
        }
    }
}

Ishlatish

Ana endi bu murakkab konvertatsiya qilingan qutichadan foydalanish shunchaki oson:

struct UIViewRepresentableBootcamp: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
            Text("Siz yozdingiz: \(text)")

            CustomUITextField(
                text: $text,
                placeholder: "Menga nimadir yozing...",
                placeholderColor: .red
            )
            .frame(height: 55)
            .background(Color.gray.opacity(0.2))
            .cornerRadius(10)
            .padding()
        }
    }
}

Xulosa:

  • makeUIView - Obyekt yaratish uchun.
  • updateUIView - SwiftUIdagi holat (@State) o'zgarganda UIKit'ni ham moslashtirish uchun.
  • Coordinator - UIKit ichidagi harakatlarni (Delegate) eshitib, SwiftUI holatiga jo'natish uchun xizmat qiladi.
Buy mea coffee