bibin-jaimon / InterviewKit-iOS

5 stars 0 forks source link

How to add UIKit inside SwiftUI project using UIViewControllerRepresentable #26

Open bibin-jaimon opened 1 month ago

bibin-jaimon commented 1 month ago

UIKit Setup

protocol UIKitCardProtocol {
    func didTapClear()
}
class UIKitCardViewController: UIViewController {
    var delegate: UIKitCardProtocol?

    private let label: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 30)
        label.textColor = .white
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private lazy var button: UIButton = {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Clear", for: .normal)
        button.backgroundColor = .red
        button.addTarget(self, action: #selector(handleClear), for: .touchUpInside)
        return button
    }()

    init() {
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(label)
        view.addSubview(button)
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])

        NSLayoutConstraint.activate([
            button.topAnchor.constraint(equalTo: label.bottomAnchor),
            button.centerXAnchor.constraint(equalTo: label.centerXAnchor),
            button.heightAnchor.constraint(equalToConstant: 50),
            button.widthAnchor.constraint(equalToConstant: 100)
        ])
    }

    func updateText(value: String) {
        self.label.text = value
    }

    @objc func handleClear() {
        delegate?.didTapClear()
    }
}

SwiftUI RepresentableView - Connector View

struct WTFCoordinator: UIKitCardProtocol {
    @Binding var text: String

    func didTapClear() {
        text.removeAll()
    }
}
struct UIKitCardRepresentableView: UIViewControllerRepresentable {
    @Binding var text: String
    typealias UIViewControllerType = UIKitCardViewController

    func makeCoordinator() -> WTFCoordinator {
        return WTFCoordinator(text: $text)
    }

    func makeUIViewController(context: Context) -> UIKitCardViewController {
        let vc = UIKitCardViewController()
        vc.delegate = context.coordinator
        return vc
    }

    // from SwiftUI to UIKit
    func updateUIViewController(_ uiViewController: UIKitCardViewController, context: Context) {
        uiViewController.updateText(value: text)
    }
}

SwiftUI Usage

struct HomeView: View {
    //    private var store = Set<AnyCancellable>()
    @State private var textValue: String = ""

    var body: some View {
        VStack {
            Text("UIRepresentable")
                .underline(true, color: .black) // Adding underline with black color
                .font(.system(size: 30)) // Setting font size to 30
            VStack {
                Text("SwiftUI View")
                TextField("Enter text here", text: $textValue)
                    .font(.system(size: 30))
                    .padding(.vertical, 10) // Add some vertical padding
                    .overlay(
                        Rectangle() // Underline
                            .frame(height: 1)
                            .padding(.top, 35) // Adjust the position of the underline
                            .foregroundColor(.black)
                    )
            }
            .padding()
            .background(.red)
            .clipShape(RoundedRectangle(cornerRadius: 25.0))

            VStack {
                Text("UIKit View")
                UIKitCardRepresentableView(text: $textValue)
                    .frame(height: 300)
                    .background(.green)
            }
            .background(.green)
            .clipShape(RoundedRectangle(cornerRadius: 25.0))

            Spacer()
        }
    }
}

struct ContentView: View {
    var body: some View {
        HomeView()
            .padding()
    }
}

#Preview {
    ContentView()
}

image