logo
hero image

Integrasi SwiftUI ke dalam UIKit

Tutorial penggunaan UIHostingController.
18 April 2022 · 6 Minutes

Setelah kita belajar mengenai cara mengintegrasikan UIKit ke dalam SwiftUI pada artikel sebelumnya, sekarang kita akan belajar untuk mengintegrasikan SwiftUI ke dalam UIKit.

Jika kamu belum membaca artikel sebelumnya, kamu bisa membacanya di sini : https://blog.alfin.dev/article/integrasi-uikit-ke-dalam-swiftui

Seperti yang kita tahu, SwiftUI -- framework baru yang diperkenalkan Apple pada WWDC19 mempunyai banyak sekali fitur yang menarik. Jika kita ingin beralih ke SwiftUI namun project kita yang existing masih menggunakan UIKit dan sudah terlalu besar, rasanya tidak mungkin untuk rewrite semuanya ke dalam SwiftUI.

Untuk mengatasi permasalahan tersebut, solusinya kita bisa migrasi ke SwiftUI secara gradually atau secara bertahap dengan cara menggunakan UIHostingController untuk menampilkan SwiftUI View ke dalam UIKit.


Apa itu UIHostingController?

icon
1open class UIHostingController<Content> : UIViewController where Content : View { ... }

UIHostingController adalah sebuah class dari module SwiftUI yang dapat kita gunakan untuk menampilkan SwiftUI View ke dalam UIKit. Class ini meng-extends dari UIViewController, sehingga kita bisa langsung tampilkan menggunakan method present atau pushViewController layaknya turunan dari class UIViewController yang lain seperti UITableViewController.

1. Menampilkan SwiftUI View ke dalam UIKit

Pertama, kita akan coba menampilkan SwiftUI View sederhana ke dalam UIKit.

Buatlah sebuah project baru kemudian pada bagian "Interface" pilih "Storyboard". Setelah itu buka file "Main.storyboard" kemudian pilih "View Controller" lalu klik menu bar "Editor -> Embed in -> Navigation Controller".

New ProjectNew Project

Setelah itu buatlah file SwiftUI View dan beri nama "SwiftUIView.swift", kemudian ubah isinya menjadi seperti ini :

SwiftUIView.swift
icon
1import SwiftUI
2
3struct SwiftUIView: View {
4 var body: some View {
5 ZStack {
6 Color.yellow
7
8 VStack {
9 Text("SwiftUI View")
10 }
11 .padding(20)
12 }
13 .navigationBarTitle("SwiftUI View")
14 }
15}

SwiftUI View di atas nantinya akan kita tampilkan melalui View Controller di UIKit.

Terakhir, ubahlah isi dari file "ViewController.swift" menjadi seperti ini :

ViewController.swift
icon
1import UIKit
2import SwiftUI
3
4class ViewController: UIViewController {
5 var button: UIButton = {
6 let button = UIButton()
7 button.backgroundColor = .systemYellow
8 button.layer.cornerRadius = 24
9 button.setTitle("Show SwiftUI View", for: .normal)
10 button.setTitleColor(.black, for: .normal)
11 button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
12 return button
13 }()
14
15 override func viewDidLoad() {
16 super.viewDidLoad()
17
18 title = "UIKit View"
19
20 view.addSubview(button)
21 }
22
23 override func viewDidLayoutSubviews() {
24 super.viewDidLayoutSubviews()
25
26 button.frame = CGRect(x: 0, y: 0, width: 200, height: 44)
27 button.center = view.center
28 }
29
30 @objc func didTapButton() {
32 let vc = UIHostingController(rootView: SwiftUIView())
33 navigationController?.pushViewController(vc, animated: true)
34 }
35}

Code di atas akan menampilkan sebuah button "Show SwiftUI View" dan jika diklik maka akan menampilkan SwiftUI View yang telah kita buat sebelumnya pada file "SwiftUIView.swift"

Untuk mengubah SwiftUI View menjadi sebuah View Controller agar bisa ditampilkan di UIKit, kita bisa lakukan dengan cara me-wrap SwiftUI View tersebut menggunakan UIHostingController :

icon
1let vc = UIHostingController(rootView: SwiftUIView())

Jika code-nya kita jalankan, maka hasilnya akan seperti ini :

Menampilkan SwiftUI View ke dalam UIKitMenampilkan SwiftUI View ke dalam UIKit

2. Passing data dari UIKit ke SwiftUI

Selanjutnya, kita akan coba passing data dari UIKit ke SwiftUI View. Silakan ubah isi dari file "SwiftUIView.swift" menjadi seperti ini :

SwiftUIView.swift
icon
1struct SwiftUIView: View {
3 var title: String
4
5 var body: some View {
6 ZStack {
7 Color.yellow
8
9 VStack {
11 Text(title)
12 }
13 .padding(20)
14 }
16 .navigationBarTitle(title)
17 }
18}

dan ubah juga method didTapButton yang ada pada class ViewController menjadi seperti ini :

ViewController.swift
icon
1@objc func didTapButton() {
2 let vc = UIHostingController(
3 rootView: SwiftUIView(
5 title: "Custom Title"
6 )
7 )
8 navigationController?.pushViewController(vc, animated: true)
9}

Jika code di atas kita jalankan, Navigation Title dan Text yang ada di SwiftUI View akan berubah menjadi "Custom Title" :

Passing data dari UIKit ke SwiftUIPassing data dari UIKit ke SwiftUI

3. Passing data dari SwiftUI ke UiKit

Terakhir, bagaimana caranya jika kita ingin mengirim balik data dari SwiftUI kepada UIKit? salah satu cara yang bisa kita gunakan adalah dengan menggunakan Closure Callback.

Sebagai contoh, kita akan membuat sebuah aplikasi sederhana yang terdiri dari 2 Screen :

  • Screen 1 : Dibuat menggunakan UIKit, bertugas untuk menampilkan label "Name"

  • Screen 2 : Dibuat menggunakan SwiftUI, bertugas untuk mengedit label "Name"

Silakan ubah isi dari file "SwiftUIView.swift" menjadi seperti ini :

SwiftUIView.swift
icon
1import SwiftUI
2
3struct SwiftUIView: View {
4 var title: String
6 var onSave: (String) -> Void
7
8 @Environment(\.presentationMode) var presentationMode
9 @State private var name: String = ""
10
11 var body: some View {
12 ZStack {
13 Color.yellow
14
15 VStack {
16 TextField("Enter your name here...", text: $name)
17 .frame(height: 44)
18 .padding(.horizontal, 20)
19 .background(.white)
20 .cornerRadius(12)
21
22 Button("Save") {
23 presentationMode.wrappedValue.dismiss()
25 onSave(name)
26 }
27 .frame(height: 44)
28 .padding(.horizontal, 20)
29 .background(.blue)
30 .foregroundColor(.white)
31 .clipShape(Capsule())
32
33 Spacer()
34 }
35 .padding(20)
36 }
37 .navigationBarTitle(title)
38 }
39}

Dan ubah juga isi dari file "ViewController.swift" menjadi seperti ini :

ViewController.swift
icon
1import UIKit
2import SwiftUI
3
4class ViewController: UIViewController {
5 var button: UIButton = {
6 let button = UIButton()
7 button.backgroundColor = .systemYellow
8 button.layer.cornerRadius = 24
9 button.setTitle("Show SwiftUI View", for: .normal)
10 button.setTitleColor(.black, for: .normal)
11 button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
12 return button
13 }()
14
15 var nameLabel: UILabel = {
16 let label = UILabel()
17 label.text = "No Name"
18 label.font = .systemFont(ofSize: 20)
19 label.textAlignment = .center
20 label.backgroundColor = .black
21 label.textColor = .white
22 return label
23 }()
24
25 override func viewDidLoad() {
26 super.viewDidLoad()
27
28 title = "UIKit View"
29
30 view.addSubview(button)
31 view.addSubview(nameLabel)
32 }
33
34 override func viewDidLayoutSubviews() {
35 super.viewDidLayoutSubviews()
36
37 button.frame = CGRect(x: 0, y: 0, width: 200, height: 44)
38 button.center = view.center
39 nameLabel.frame = CGRect(
40 x: 20,
41 y: button.frame.origin.y + 100,
42 width: view.frame.size.width - 40,
43 height: button.frame.size.height
44 )
45 }
46
47 @objc func didTapButton() {
48 let vc = UIHostingController(
49 rootView: SwiftUIView(
50 title: "SwiftUI View",
52 onSave: { [weak self] name in
53 self?.nameLabel.text = "Name: \(name)"
54 }
56 )
57 )
58 navigationController?.pushViewController(vc, animated: true)
59 }
60}

Penjelasan kode :

icon
1Button("Save") {
2 presentationMode.wrappedValue.dismiss()
3 onSave(name)
4}
  1. Ketika button "Save" ditekan, maka akan kembali ke screen utama dan akan memanggil callback onSave sambil membawa data name

icon
1let vc = UIHostingController(
2 rootView: SwiftUIView(
3 title: "SwiftUI View",
4 onSave: { [weak self] name in
5 self?.nameLabel.text = "Name: \(name)"
6 }
7 )
8)
  1. Ketika callback onSave dipanggil, kita update text dari nameLabel sesuai dengan parameter name

  2. Kita juga menggunakan Capture List weak pada closure onSave agar tidak terjadi Strong Reference Cycle.

Kamu bisa membaca artikel saya tentang Automatic Reference Counting (ARC), Strong Reference Cycle, dan Capture List pada bahasa pemrograman Swift di sini : https://blog.alfin.dev/article/memory-management-pada-swift

Jika code di atas kita jalankan, maka hasilnya akan seperti ini :

Passing data dari SwiftUI ke UiKitPassing data dari SwiftUI ke UiKit


Oke mungkin itu saja yang bisa saya bagikan kali ini, kalau kamu merasa artikel ini bermanfaat silakan Like & Share artikel ini ke teman-teman kamu atau jika kamu punya pertanyaan, tulis aja di kolom komentar, Thank you! 😁 🙏

iOS Development
Swift
SwiftUI
UIKit

Written by :
Alfin Syahruddin
Developer · Stock Trader · Libertarian · Freethinker

Always open to new ideas. 🕊️

Loading...

Related articles

Articles that you might want to read.

hero image
Integrasi UIKit ke dalam SwiftUI

Tutorial penggunaan UIViewRepresentable dan UIViewControllerRepresentable.

17 April 2022 · 11 Minutes
iOS Development
Swift
SwiftUI
UIKit
hero image
CI/CD aplikasi iOS dengan Xcode Cloud

Otomatisasi build, testing, dan deployment aplikasi iOS ke Testflight & AppStore.

27 January 2024 · 8 Minutes
iOS Development
CI/CD
Xcode Cloud
hero image
DocC Tutorial

Dokumentasikan project-mu dengan DocC!

19 March 2023 · 8 Minutes
iOS Development
Swift
DocC
CI/CD
All rights reserved © Alfin Syahruddin · 2019
RSS Feed