Your first complex application in SwiftUI

Giovanni Erpete
Apple Developer Academy | Federico II
6 min readJun 19, 2020

--

Saying welcome to Model View ViewModel (MVVM) pattern using SwiftUI.

If you’ve heard of SwiftUI but you have never dealt with this framework, you’re in the right place.

During the 2019 WWDC, Apple introduced SwiftUI, a new framework that, in the plans of the American company, will change the way applications are made. SwiftUI will eventually replace the existing UIKit. Actually SwiftUI is a wrapper of UIKit but despite this the differences between the two are many, just think that storyboards will no longer exist and that a new procedural paradigm is applied allowing you to make the code easily exportable on all Apple devices.

https://developer.apple.com/documentation/swiftui

Precisely these novelties make SwiftUI to have a great potential and it is thought that in the coming years it can definitively replaces its ancestors , precisely for its ease in writing code, due to the imperative paradigm, like Python and Ruby, making the very same code to adapt to the various screens of the devices.

We would love to say it’s enough for the differences, but here comes the big one: when you use swiftUI you abandon the classic Model-View-Controller (MVC) design pattern in favour of the latest Model-View-ViewModel (MVVM)

The design pattern:

This pattern, developed by Ken Cooper and Ted Peters of Microsoft, was designed to simplify event driven programming.

Model View ViewModel pattern architecture

Its scheme, allows us to immediately notice its four fundamentals elements:

  1. Model: MVVM is an implementation of the Domain Model pattern. The Model will include our data structure and business logic and validation logic.
  2. View: View will be responsible for defining the structure, layout and appearance of what the user sees on the screen.
  3. ViewModel : the ViewModel will be the intermediary between the view and the model. It is responsible for the management of the logic of the view. Generally, the view model interacts with the model by invoking methods in the model classes. The view model will then provide the model data in such a way that the view can use it easily.
  4. DataBinding : Data binding is a fundamental mechanism for this pattern: with this operation the view model and the view are kept constantly synchronized, typically through a declarative syntax in the view itself. This implies that changes to the data made by the user through a view will be automatically reported in the view model, without giving this responsibility to the developer.

The question that this article wants to answer is the following: Is SwiftUI ready to handle a complete application? Or is he still too young and needs more time to express his true potential?

Our first application in SwiftUI:

To try to answer these questions we decided , as students of the Apple Developer Academy in Naples, to develop a full SwiftUI application to better understand its potential and the main differences with UIKit. This application is called Planooze: it is an app for tourists that will show you the shortest path to reach all the points of interest that you intend to visit. In addition to using SwiftUI, during this project we used other frameworks such as MapKit, CoreLocation, CoreData and CloudKit.

We will focus in particular on the part of MapKit and CoreLocation, which manages the creation of the routes.

Taking in account what we previously discussed about the framework itself our project met these four components : Model, ViewModel, View and Data Binding.

Let’s examine them in more detail:

Model: Our model is made of Itinerarymodel.swift, Searchinput.swift and Locationmanager.swift.

Itinerarymodel.swift is a data structure that allows you to keep track of the points of interest that are chosen and then calculate the shortest path.

SearchInput.swift, on the other hand, manages the search for points of interest. The search for points of interest can be done in two ways: the first way through the search by names, the second through filters by the category of points of interest (café, museum, ect.).

Locationmanager.swift finally, is the model that allows us to take our current position.

ViewModel: our Viewmodel is the Mapviewmodel.swift file .

The Viewmodel will return an element of the view that in our case is a MKMapView.

Here the Mapviewmodel can inherit the UIViewRepresentable or UIViewControllerRepresentable protocol and to do this we have to write some code.

No need to overthink about, just do it.

First we need to declare a coordinator. The coordinators in swiftUI are designed to act as the delegate for UIKit ViewControllers. In fact it will be a class that can extend the MKMapViewDelegate in our case .

A delegate is the protocol responsible for handling the data source of your model.

In the coordinator we will have a reference to our ViewModel and we will define all the functions that will allow us to invalidate the view in order to update it in response to changes in the model. In addition we need to define a makeCoordinator() function that returns the coordinator creating a communication between the ViewModel and the Coordinator itself.

The make(context: _ ) and update(view: _, context: _ ) functions are the functions that are called respectively when the view is created for the first time and when it needs to be updated.

View: In our project we have three views that are shown to a final user: ContentView.swift, PoiDetailsView.swift and PlaceListView.swift.

The ContentView will be responsible for showing the MKMapView and the PlaceListView.swift. When you tap on a point of interest a modal called PoiDetailsView.swift will be showed giving you the chance to add a point of interest to your own path and to calculate the best itinerary.

Data Binding: As we have previously mentioned, data binding is a fundamental operation for this pattern. In order to communicate viewModel and view we need these binding.

In swift the data binding can be expressed through various tags:

  • @Binding: allows us to declare that a value actually comes from elsewhere and must be shared within these contexts;
  • @ObservedObject and @EnvironmentObject: they are two properties similar to that of binding, only that they have a greater sharing scope , potentially making an object with one of these 2 tags to be shared between all the views of the application;
  • @Published and ObservableObject protocol: allows us to create observable objects that announce automatically when changes occur. All classes that are compliant with the Observableobject protocol can be used within SwiftUI and notify when its values have change so that you know when to update the view.
  • @State: it’s a tag that allows us to check the value of our Binding ,ObservedObject or EnvironmentObject. SwiftUI decides whether to invalidate the view or not if the value of the @State tag changes or not.

Through these tags we can make the ViewModel and the View communicate.

During the development of our application, we realised that SwiftUI can already be a valid alternative to UIKit: it allows developers to focus more on the application’s implementation logic rather than “wasting” time caring about things like auto-layout. So while it’s still young as a framework, our advice is to try it out. Perhaps the only problem we encountered is the lack of examples of code, but with the time passing by , the available documentation will surely become wider.

We hope that this article will work in this direction.

Link TestFlight to Planooze:

Link to Planooze medium article:

https://medium.com/@antonellacirma/71f4da6b5388

Group:

Simone Punzo

Mauro Zobel
(https://www.linkedin.com/in/mauro-zobel-321120196/)

Giovanni Erpete
(https://www.linkedin.com/in/giovanni-erpete-51035617b/)

Giovanni Di Guida
(https://www.linkedin.com/in/giovanni-di-guida-228287165/)

Simone De Crescenzo
(https://www.linkedin.com/in/simone-de-crescenzo-4081461b0/)

Mirella Cetronio
(https://www.linkedin.com/in/mirellacetronio/)

Antonietta Cirma
(https://www.linkedin.com/in/antonella-cirma-814295114/)

Link to GitHub repo for the project:

--

--