SlideShare a Scribd company logo
1 of 68
When You Can’t Go All In on SwiftUI,
Build a Hybrid UI App Instead!
Vui Nguyen
@sunfishgurl
360iDev, 2022
Video: https://bit.ly/TipperSwiftUIBefore
Video: https://bit.ly/TipperUIKitBefore
SwiftUI
I’m Vui Nguyen
long time software engineer (20+ years) across many tech
stacks
had to learn both new tech & maintain old tech over my career
currently native iOS developer
started mobile development as cross platform dev
may explain my interest in interoperability
also worked on hybrid Objective-C & Swift apps
enjoys feeding animals at zoos
Introduce the problem
Who am I?
Why solve this problem?
The UI “flow” and how SwiftUI and UIKit fit in that flow
UIKit Tip Calculator: code overview
SwiftUI Tip Calculator: code overview
Case 1: SwiftUI app -> Add UIKit component
Case 2: SwiftUI app -> Add UIKit screen
Case 3: UIKit app -> Add SwiftUI component
Case 4: UIKit app -> Add SwiftUI screen
Resources
What’s not covered: deep dive into how UIKit or SwiftUI
works
maintain legacy apps while keeping current with modern technologies
leverage strengths of other frameworks on an as-needed basis
migration from UIKit -> SwiftUI, for example, doesn’t have to happen
overnight or be 100% complete
your app can stay hybrid “forever”, hybrid ratio depends on YOUR
project needs!
do this while minimizing project risks
The “inform app of
state change” &
“action / delegate
updates UI” steps
from UIKit you get for
FREE with SwiftUI
SwiftUI accomplishes
same thing by
binding state
variables to views
Building a hybrid UI app is possible if you
In SwiftUI apps, add code to UIKit components/screens to:
Inform app of changes to state / data, so that
SwiftUI views that are listening can refresh themselves
In UIKit apps:
Use correct property wrappers to bind data to SwiftUI views
Publish variables for UIKit views/viewcontrollers to listen for
changes to
Tip Calculator in UIKit ->
Code Overview
UIKit
Tip Calculator in SwiftUI ->
Code Overview
Case 1: SwiftUI App ->
Add UIKit component
Before After
Video: https://bit.ly/TipperSwiftUIAfter
Video: https://bit.ly/TipperSwiftUIAfter
Before
After
Coordinator != navigation pattern
Implement UIViewRepresentable protocol
creates SwiftUI wrapper around UIKit View
Coordinator pattern implements missing UIKit target-
action pattern
Case 2: SwiftUI App ->
Add UIKit screen
SwiftUI
Before Payscreen
Video: https://bit.ly/TipperSwiftUIPayscreen
Video: https://bit.ly/TipperSwiftUIPayscreen
SwiftUI
storyboard
SwiftUI
PaymentViewController
SwiftUI
PaymentViewController.View is a SwiftUI
wrapper around PaymentViewController
implements
UIViewControllerRepresentable
storyboard
SwiftUI
SwiftUI PaymentViewControllerDelegate
PaymentViewControllerDelegate
sets values of paymentMethod &
payState
The main SwiftUI view, listening
to changes to these variables, will
update itself
storyboard
Coordinator != navigation pattern
SwiftUI
SwiftUI
SwiftUI
Implement UIViewControllerRepresentable protocol
creates SwiftUI wrapper around UIKit ViewController
Coordinator pattern implements missing UIKit delegate
pattern
Case 3: UIKit App ->
Add SwiftUI Component
Before After
Video: https://bit.ly/TipperUIKitAfter
Video: https://bit.ly/TipperUIKitAfter
Before After
Play gif here
Add Container View to hold Hosting Controller, which holds
SwiftUI View
Use correct property wrappers: @ObservedObject,
@Binding, etc to bind data to SwiftUI Views
Publish variables that you want UIKit or SwiftUI views to
listen for changes to
Case 4: UIKit App ->
Add SwiftUI Screen
Before Payscreen
Video: https://bit.ly/TipperUIKitPayscreen
Video: https://bit.ly/TipperUIKitPayscreen
Play gif here
Add Hosting Controller to hold SwiftUI View
Use correct property wrappers: @ObservedObject,
@Binding, etc to bind data to SwiftUI Views
Publish variables that you want UIKit or SwiftUI views to
listen for changes to
Building a hybrid UI app is possible if you
In SwiftUI apps, add code to UIKit components/screens to:
Inform app of changes to state / data, so that
SwiftUI views that are listening can refresh themselves
In UIKit apps:
Use correct property wrappers to bind data to SwiftUI views
Publish variables for UIKit views/viewcontrollers to listen for
changes to
https://github.com/vuinguyen/TipperUIKit
https://github.com/vuinguyen/TipperSwiftUI
branches: before, after, payscreen
Drawing tool: https://excalidraw.com/
Code formatting: https://carbon.now.sh
https://developer.apple.com/documentation/swiftui/swiftui-views-
displayed-by-other-ui-frameworks
https://developer.apple.com/documentation/swiftui/other-ui-framework-
views-displayed-by-swiftui
https://www.raywenderlich.com/19165608-integrating-uikit-swiftui
SwiftUI Views in Table & Collection Cells:
https://developer.apple.com/videos/play/wwdc2022/10056/
Introduce the problem
Who am I?
Why solve this problem?
The UI “flow” and how SwiftUI and UIKit fit in that flow
UIKit Tip Calculator: code overview
SwiftUI Tip Calculator: code overview
Case 1: SwiftUI app -> Add UIKit component
Case 2: SwiftUI app -> Add UIKit screen
Case 3: UIKit app -> Add SwiftUI component
Case 4: UIKit app -> Add SwiftUI screen
Resources
What’s not covered: deep dive into how UIKit or SwiftUI
works
Connect with me!
I’m Vui Nguyen
Website: sunfishempire.com
Twitter: sunfishgurl
Github: vuinguyen
email: vui@atomicrobot.com

More Related Content

Similar to When You Can’t Go All In on SwiftUI, Build a Hybrid UI App Instead!

Puppet Integration Adapter - Datasheet
Puppet Integration Adapter - DatasheetPuppet Integration Adapter - Datasheet
Puppet Integration Adapter - DatasheetKovair
 
How to integrate portlet as widget in liferay to any website application
How to integrate portlet as widget in liferay to any website applicationHow to integrate portlet as widget in liferay to any website application
How to integrate portlet as widget in liferay to any website applicationAzilen Technologies Pvt. Ltd.
 
Developing Online Application with Kivy A Python Framework
Developing Online Application with Kivy A Python FrameworkDeveloping Online Application with Kivy A Python Framework
Developing Online Application with Kivy A Python Frameworkijtsrd
 
Tizen-based Samsung TV SDK Overview
Tizen-based Samsung TV SDK OverviewTizen-based Samsung TV SDK Overview
Tizen-based Samsung TV SDK OverviewRyo Jin
 
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...Wasura Wattearachchi
 
Magento Community Hangouts 10 Feb, 2021 PHP 8 support
Magento Community Hangouts  10 Feb, 2021 PHP 8 supportMagento Community Hangouts  10 Feb, 2021 PHP 8 support
Magento Community Hangouts 10 Feb, 2021 PHP 8 supportStanislavIdolov
 
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...Ortus Solutions, Corp
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributesMarco Eidinger
 
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...Igalia
 
UI Testing for Your Xamarin.Forms Apps
UI Testing for Your Xamarin.Forms AppsUI Testing for Your Xamarin.Forms Apps
UI Testing for Your Xamarin.Forms AppsCodrina Merigo
 
The WebKit project (LinuxCon North America 2012)
The WebKit project (LinuxCon North America 2012)The WebKit project (LinuxCon North America 2012)
The WebKit project (LinuxCon North America 2012)Igalia
 
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integration
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket IntegrationImplementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integration
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integrationsandeepmenon62
 
Vuejs for Angular developers
Vuejs for Angular developersVuejs for Angular developers
Vuejs for Angular developersMikhail Kuznetcov
 
Case study on Movie Quiz App For IPhone and IPad – Facebook Enabled
Case study on Movie Quiz App For IPhone and IPad –  Facebook Enabled Case study on Movie Quiz App For IPhone and IPad –  Facebook Enabled
Case study on Movie Quiz App For IPhone and IPad – Facebook Enabled Grey Matter India Technologies PVT LTD
 
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...Matt Raible
 
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloak
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloakDevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloak
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloakHitachi, Ltd. OSS Solution Center.
 
What’s New in iOS 8 SDK ?
What’s New in iOS 8 SDK ?What’s New in iOS 8 SDK ?
What’s New in iOS 8 SDK ?E2LOGY
 

Similar to When You Can’t Go All In on SwiftUI, Build a Hybrid UI App Instead! (20)

Puppet Integration Adapter - Datasheet
Puppet Integration Adapter - DatasheetPuppet Integration Adapter - Datasheet
Puppet Integration Adapter - Datasheet
 
watch_kit_v_1.0
watch_kit_v_1.0watch_kit_v_1.0
watch_kit_v_1.0
 
How to integrate portlet as widget in liferay to any website application
How to integrate portlet as widget in liferay to any website applicationHow to integrate portlet as widget in liferay to any website application
How to integrate portlet as widget in liferay to any website application
 
Developing Online Application with Kivy A Python Framework
Developing Online Application with Kivy A Python FrameworkDeveloping Online Application with Kivy A Python Framework
Developing Online Application with Kivy A Python Framework
 
Tizen-based Samsung TV SDK Overview
Tizen-based Samsung TV SDK OverviewTizen-based Samsung TV SDK Overview
Tizen-based Samsung TV SDK Overview
 
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...
WSO2 Screencast - How to Easily Build a Git-Based CI/CD Pipeline for your API...
 
Magento Community Hangouts 10 Feb, 2021 PHP 8 support
Magento Community Hangouts  10 Feb, 2021 PHP 8 supportMagento Community Hangouts  10 Feb, 2021 PHP 8 support
Magento Community Hangouts 10 Feb, 2021 PHP 8 support
 
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributes
 
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...
WebKit and Blink: Open Development Powering the HTML5 Revolution (LinuxCon No...
 
UI Testing for Your Xamarin.Forms Apps
UI Testing for Your Xamarin.Forms AppsUI Testing for Your Xamarin.Forms Apps
UI Testing for Your Xamarin.Forms Apps
 
The WebKit project (LinuxCon North America 2012)
The WebKit project (LinuxCon North America 2012)The WebKit project (LinuxCon North America 2012)
The WebKit project (LinuxCon North America 2012)
 
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integration
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket IntegrationImplementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integration
Implementing CloudHub 2.0 CI/CD Pipeline with Bitbucket Integration
 
Web 2
Web 2Web 2
Web 2
 
Vuejs for Angular developers
Vuejs for Angular developersVuejs for Angular developers
Vuejs for Angular developers
 
Case study on Movie Quiz App For IPhone and IPad – Facebook Enabled
Case study on Movie Quiz App For IPhone and IPad –  Facebook Enabled Case study on Movie Quiz App For IPhone and IPad –  Facebook Enabled
Case study on Movie Quiz App For IPhone and IPad – Facebook Enabled
 
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
 
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloak
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloakDevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloak
DevConf.CZ 2020 @ Brno, Czech Republic : WebAuthn support for keycloak
 
What’s New in iOS 8 SDK ?
What’s New in iOS 8 SDK ?What’s New in iOS 8 SDK ?
What’s New in iOS 8 SDK ?
 
EVOLVE'15 | Enhance | Bob O'Conner & Kevin Nenning | Capturing Existing Cont...
EVOLVE'15 | Enhance |  Bob O'Conner & Kevin Nenning | Capturing Existing Cont...EVOLVE'15 | Enhance |  Bob O'Conner & Kevin Nenning | Capturing Existing Cont...
EVOLVE'15 | Enhance | Bob O'Conner & Kevin Nenning | Capturing Existing Cont...
 

Recently uploaded

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 

When You Can’t Go All In on SwiftUI, Build a Hybrid UI App Instead!

Editor's Notes

  1. Hello! Welcome to my talk called “When you can’t go all in on SwiftUI, build a hybrid UI app instead!” My name is Vui Nguyen
  2. So, let’s start off with an app we want to build. How about something simple to start, like a tip calculator? Should we use SwiftUI to build it since that’s what Apple recommends we use now? Well, let’s see how how this tip calculator turned out ….. - Well, this tip calculator looks and works fine. I sure wish I could customize the colors on this segmented control though. In fact, the requirements for this project states that the selected indicator should be a color that stands out, so you know it’s been selected.
  3. Let’s try building this tip calculator in UIKit next …. This looks much better. But you know, I sure wish we could have used SwiftUI. Maybe not for the segmented control, but maybe for this tip amount and bill amount boxes. I bet you we could turn this into a reusable SwiftUI component so at least we can integrate SwiftUI where we can, so we can start taking advantage of the benefits of SwiftUI instead of staying in the dark ages. And rewriting the tip amount and bill total boxes as a reusable SwiftUI component could be built cleaner and with less code using SwiftUI. Well guess what? You don’t have to choose either SwiftUI OR UIKit when building your iOS apps! You can mix and match components of both frameworks depending on your project needs, and today I’ll show you how to do that!
  4. But before we get much further …. let me introduce myself. as a long time software engineer, I’ve worked across many different tech stacks. So, keeping up with new technologies is important to me. And I’ve also had my share of maintaining many legacy apps over my career. Because I’ve also been a cross platform mobile developer, that may also explain my interest in building systems that are interoperable across platforms or across languages! And I think there’s a need for a solution to this problem because Apple keeps coming out with new stuff, but we still gotta maintain all their old stuff.
  5. Today we’re going to cover how to build hybrid UI apps. I’ve introduced the problem we’re trying to solve, and introduced myself! Next, we’ll cover why we want to solve this problem …….
  6. In Resources, I will share links so you may continue learning on your own, plus the links to all my project code
  7. - How many times have you worked on a really old app and wanted to just scrap all of it and start over? How many times have you been told, no, we can’t afford to do this. We can only afford to fix this or maintain it, or add to it. So what do you do? What about some of the cool new developments in SwiftUI? Like SwiftUI charts? Wouldn’t it be nice to integrate some of that now? Have you been frustrated if you started building in SwiftUI and starting running into edge cases & wish you could pull in a UIKit component that you know works?
  8. Let’s start by going over the UIKit and SwiftUI flows first, to see how they’re the same and how they’re different, before we can talk about how to make them play nicely together
  9. Now, based on the UI flows I just showed you, here’s a takeaway point I want you to keep in mind when I go over the 4 use cases of hybrid UI apps in a bit ….
  10. Also, now that we’ve gone over, at a high level, the UI flow for UIKit and SwiftUI, let’s briefly go over the code for the tip calculator in UIKit. This will help provide a foundation for the 4 different use cases of hybrid UI apps later ….
  11. Keep in mind , for these code snippets, I often took out styling and other things, so code can fit on the slide & you can focus on just the topic for that slide and nothing else! But the entire working code is available on my Github, where I will share the links later. In TipperViewController.swift: - Here we add a target-action, which is a UIKit pattern, to the segmentedControl - That way, we can inform the app that the tip percent has changed and to call updateDisplay to update tip amount and bill total
  12. In TipperViewController: - Here we also want to inform the app when the bill amount changes, and to call updateDisplay so that the tip amount and bill total can be updated - We do this through the Delegate pattern of UIKit, by implementing UITextFieldDelegate, which gets called when the value in the bill amount text box changes
  13. In TipperViewController: When the app has been informed that either the bill amount or tip percent has changed, updateDisplay gets called, which updates the tip amount and bill total.
  14. Now, let’s briefly go over the tip calculator in SwiftUI, before we dive into the 4 use cases of hybrid UI apps ….
  15. SIMULATOR: SwiftUI BEFORE In ContentView.swift: - We start by binding the state variable, selectedTipPercentage, to the picker, so changes to the picker can update the selectedTipPercentage variable - We want to have CalculatedAmountView, which is a reusable SwiftUI component, to listen to changes in selectedTipPercentage and re-calculate and re-display the updated tip amount and bill total, as needed
  16. In ContentView.swift: - We also want to bind the billAmount state variable to the textfield, so changes to the textfield can update the billAmount variable have CalculatedAmountView listen to changes in billAmount and re-calculate and re-display updated tip amount and bill total, as needed
  17. Now back in our reusable SwiftUI component, that we call CalculatedAmountView, will be used to display either the Tip Amount or the bill Total, depending on the label type and the amount type. Here we’re in the preview screen for the CalculatedAmountView displaying what the the Tip Amount view would look like
  18. In ContentView.swift: back in the ContentView, notice we have 2 CalculatedAmountViews, one is used to display the tip amount and the other is used to display the bill total Here’s how they look individually in the SwiftUI preview windows for each of them, and how they look like together in the preview window for the entire screen
  19. Now that we’ve done a quick overview of the Tip Calculator code in both UIKit and SwiftUI, let’s go over the 1st use case in this talk. So, let’s say you have a single screen SwiftUI app and you want to add a UIKit component to that same screen.
  20. So, let’s revisit that SwiftUI tip calculator with the wonky looking segment control for the tip percent. Let’s replace that SwiftUI segment control with a UIKit segmented control that we can customize, so we can more easily see which tip percent was selected
  21. Let’s run a quick demo video of the tip calculator
  22. In ContentView.swift: swap Picker with SegmentedControl SegmentedControl is the new SwiftUI view that was created, which is a wrapper around UISegmentedControl (a UIKit component)
  23. In SegmentedControl.swift: - UISegmentedControl is UIKit component, in order to drop it into our SwiftUI screen, we need to create a SwiftUI wrapper view around it To do this, we need to implement the makeUIView function of the UIViewRepresentable protocol (an Apple API), which will creates a SwiftUI view wrapper around our UISegmentedControl (UIKit component) notice how you add the target-action to the UISegmentedControl inside the makeUIView function just as if it was a regular UIKit component notice also how the action function is defined inside something called a Coordinator, which I will explain in a bit
  24. In SegmentedControl.swift: in the UIViewRepresentable protocol, we also have an updateUIView function that we need to implement updateUIView updates the SegmentedControl display when user taps on the SegmentedControl Notice something called a Context, this Context stores the state of the app, and we get to the state of the app through a Coordinator
  25. In SegmentedControl.swift: Since SegmentedControl is, under the covers, a UISegmentedControl, or a UIKit component, we need to use a UIKit pattern to inform the app when the SegmentedControl has been tapped, and the selectedTipPercentage variable has been updated. We do that by making a Coordinator. Note, this Coordinator is NOT the same as the UIKit navigation pattern. This Coordinator is part of the Apple protocol, UIViewRepresentable since the Coordinator, is an object with access to the context or state of the app, we use the Coordinator to implement the UISegmentedControl’s (UIKit component’s) target-action pattern, which it is doing through this tipPercentChanged function. tipPercentChanged informs the app when there are changes to selectedTipPercentage. Once the app has been “informed” of changes to selectedTipPercentage, then whatever views that are listening for those changes, can update themselves.
  26. In SegmentedControl.swift: and here we implement the makeCoordinator function of the UIViewRepresentable protocol, to make a Coordinator available for the SegmentedControl And of course, once the Coordinator is available, then the Coordinator can implement the missing UIKit patterns we need for our SegmentedControl
  27. - Now that we’ve gone over how the SegmentedControl was implemented, let’s go back to how updating the tip percent updates the calculation for tip amount and bill total automatically. - The SegmentedControl listens for when the user taps on the control and changes the value of the selectedTipPercentage. - The Tip Amount and Bill Total boxes, are listening to changes in the selectedTipPercentage, and automatically update their calculations and re-display their values when selectedTipPercentage gets updated.
  28. Also when bill amount changes, that automatically updates the bill amount used in calculating the tip amount and bill total. Again, we do not have to inform the TipAmount or Bill Total views that the bill amount has changed and therefore recalculate the tip amount and bill total. That happens automagically since the billAmount variable are bound to those views (those views are listening to changes in bill amount!)
  29. Now, let’s quickly recap what we just went over When you have a single screen SwiftUI app and you want to add a UIKit component to that screen, you do that by ….
  30. Now that we know how to add a UIKit component to a SwiftUI screen, let’s go over our next use case. Let’s say we have a single screen SwiftUI app and now this time we want to add a second screen. This second screen was built in UIKit.
  31. So we’re back to our SwiftUI Tip calculator. The main screen is still calculating our tip. - Let’s say, once we’re done calculating the tip, we’re ready to pay. - And this time, we want to add a UIKit screen that allows us to select our payment method. - Once we select the payment method on the second screen, we go back to the main screen and it displays the payment method that we selected.
  32. Let’s play the brief demo video. See how the tip percent you selected determines the image you see in the second screen ….
  33. Let’s start on the main screen. We need to add the Pay button and the Paid by label. They will be displayed or hidden based on the state variables paymentMethod and payState. We also need to be able to segue to the payment screen once we tap on the Pay button. This is possible through the NavigationLink which will open the PaymentViewController, the payment screen, when we tap on the Pay button.
  34. Let’s create a new PaymentViewController storyboard for the second screen and a PaymentViewController to go with it! Notice we also have a protocol PaymentViewControllerDelegate that we need to implement When the user taps on the payment method segmented control, the paymentMethod gets updated We then need to inform the app, through the Delegate function, paymentSelector, that the paymentMethod has been updated, so that the app, through the delegate, can act on this change in state. So, for example, we’ll want to update the Paid By label on the main screen with the payment method once it’s been selected. This is the Delegate pattern of UIKit
  35. - But in order to use this UIKit screen, PaymentViewControl, in our SwiftUI app, we need to create a SwiftUI wrapper around it. - We create a SwiftUI wrapper, called PaymentViewController.View, by implementing the UIViewControllerRepresentable protocol
  36. To create a SwiftUI wrapper around PaymentViewController (which is a UIViewController built from a traditional storyboard), we need to implement the makeUIViewController function, which is part of the UIViewControllerRepresentable protocol - we’re required to have an updateUIViewController function because it’s part of the UIViewControllerRepresentable protocol, but there’s nothing in it since there is no component on this screen that needs to be updated as a result of change in state That’s because when the paymentMethod SegmentedControl gets updated, we want to inform the main screen of this, which will happen through the Delegate method. But nothing on the payment screen (outside of the picker) needs to be updated as a result of the segmentedControl’s new value
  37. Now, remember earlier I said we needed to implement the PaymentViewControllerDelegate protocol? So, here we are implementing the paymentSelector function of PaymentViewControllerDelegate. in paymentSelector, we take the paymentMethod that the user selected from the payment segmentedControl and set it to the state variable paymentMethod also set the payState to paid - We are using @Binding for the state variables here because the delegate could change the values of the state variables and we want those changed values to be reflected back in the main ContentView (SwiftUI view)
  38. - But who creates the PaymentViewControllerDelegate? - makeCoordinator is where we create a PaymentViewControllerDelegate The Coordinator pattern allows us to implement the Delegate pattern for UIKit ViewControllers within a SwiftUI app Remember, this Coordinator pattern is part of the UIViewControllerRepresentable protocol and is not the same thing as the UIKit navigation pattern.
  39. - Now, going back to the main screen ….. - now that the state variables have been updated, that will hide the Pay button which has been listening to the value of payState
  40. Also when payState and paymentMethod are updated, that now shows the Paid By label, and displays the paymentMethod that was selected in the second screen
  41. Now let’s quickly recap what we did. For our 2nd use case, we had a single screen SwiftUI app, and we wanted to add a second screen in UIKit. To do that ….
  42. So, we went over a couple of use cases with SwiftUI apps and added a UIKit component or UIKit screen. Now, let’s shift to a couple of new use cases starting with a UIKit app. So, let’s say you have a UIKit app and now you want to add a SwiftUI component ….
  43. - In this case, we see that the Tip Amount and Bill Total boxes look very similar. The actual text and dollar amounts are different. What if we could replace both of those with a single reusable SwiftUI component. I’ll show you how to do that next. I made the font and colors of this new SwiftUI component look different from the UIKit one, just so you can easily see that I made a change.
  44. Now, let’s briefly view the demo video.
  45. - I order to swap out the UIKit components for Tip Amount and Bill Total with a reusable Swift component, we’ll first need to remove the original tip amount and bill total views and put container views in their place - These Container Views will segue to a couple of hosting view controllers, which will eventually hold our new SwiftUI views
  46. This is a bigger view of the Container Views and their segues to the hosting view controllers
  47. - Now we want to access those segues in the code by adding IBSegueActions. Here’s a gif that shows you how to do that. Control-click on the segue to the TipperViewController to create IBSegueActions to the HostingControllers Do one for the tip amount, and we do the same thing for the bill total Here it is in action! Next slide ….
  48. - IBSegueAction is special segue to a UIHostingController, which holds our SwiftUI View, in this case, the Tip Amount or Bill Total The CalculatedAmountView will display either the tipAmount or billTotal depending on the CalculatedAmountType Which is an enum of the value tipAmount or billTotal
  49. - Now, let’s take a look at our reusable SwiftUI component, CalculatedAmountView - This view is used to display Tip Amount or Bill Total, depending on the value of amountLabel and amount. also this view is listening to changes in the tipPercent and billAmount values, which are Published properties in TipperViewModel
  50. - Now, the appropriate values will show in the Tip Amount and Bill Total views, as you can see in the SwiftUI previews for the container views - and when both views are together in the main screen
  51. Now, let’s quickly recap what we learned.
  52. Finally, let’s go over our fourth and final use case. Let’s say you have a single screen UIKit app and now you want to add a second screen in SwiftUI
  53. Let’s go back to our infamous UIKit Tip calculator. We still want to select our payment method on the second screen after calculating our tip on the main screen. But this time, we’re going to build the payment screen in SwiftUI. And since segmented controls don’t look so great in SwiftUI, we’re going to use buttons to select the payment method for our SwiftUI screen
  54. Let’s play a brief demo video. - Once again, the tip percent you select determines the image you see on the second screen. Then, the payment method you select on the second screen gets reflected back on the main screen.
  55. - We start by adding the Pay button and Paid by label on the main screen in the storyboard. - We want, when we tap on the Pay button, to segue to the payment screen. - we start doing this by Creating a IBSegueAction from the segue in the Storyboard to the ViewController. This is where you will segue to the HostingController! (next slide)
  56. - we need to add outlets for the Pay button and Paid by label. Notice also how the IBSegueAction returns a UIHostingController. The UIHostingController is a UIKit wrapper around the SwiftUI view we want to present in this case, we will be presenting the PaymentView, or the second screen, which we are building in SwiftUI
  57. - Here’s the second screen, PaymentView, built in SwiftUI! Here we set the paymentMethod based on which paymentMethod button the user taps on. Also, by selecting the paymentMethod, we are also setting the payState to paid
  58. Finally, when we return to the main screen, the Pay button is updated appropriately (which, in this case, is hidden). And that’s because, paymentMethod and payState are Published properties of TipperViewModel, and the Pay button has been listening to changes in the states
  59. - Since UIKit views and view controllers don’t bind to state variables the way that SwiftUI views do, we need to make our viewModel an observableObject, and we need to publish the variables that we want our view controller to listen for changes to. This way, we don’t have to inform the main view controller through a delegate or target-action pattern that those Published variables have changed because the main view controller is listening for those changes automatically But because the main view controller is still in UIKit, we will need to manually call the updatePaySection function to update the Pay button when we return to the main screen (through viewWillAppear) and when the billAmount or tipPercent changes
  60. - And again, when we return to the main screen, the Paid By label is displayed with the paymentMethod set from the second screen. - And again, that’s because, paymentMethod and payState are Published properties of TipperViewModel and the Paid By label are listening to changes in their states
  61. Alright, let’s recap what we just learned!
  62. So, to start wrapping up, Remember our takeaway point from earlier on how to build hybrid SwiftUI and UIKit apps …..
  63. This is what we’ve covered today …..
  64. Any questions later, you may contact me through social media or my work email. I might give this talk again at another meetup or conference, so I welcome feedback on how I can improve.