Key Features • Hello Case • Contacts Case • Auto Layout • Credits • License
We will explore the difference between UIKit and SwiftUI with multiple projects
How to use:
The MVC (Model-View-Controller) pattern is a traditional software design pattern that has been used in UIKit, Apple’s traditional UI framework for iOS apps. On the other hand, the MV pattern (Model-View) is a pattern that is commonly used in SwiftUI, Apple’s newer UI framework for iOS apps.
The main difference between the two patterns is that MVC has three components: Model, View, and Controller, while MV has two components: Model and View. In MVC, the Controller acts as an intermediary between the Model and the View, whereas in MV, the View and the Model are more tightly coupled.
In the Hello example i’ve used UIKit interface builder for create the view and manage the padding.
The main difference with SwiftUI when you manage the project are the AppDelegate and SceneDelegate.
AppDelegate methods are called for application level lifecycle events. In the default AppDelegate.swift there are three methods that Apple considers to be important that we have to consider and let’s look into them:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
An app can have more than one scene which mostly handles application interface and app content. So, the SceneDelegate is responsible for what’s displayed on the screen in terma of UI and data.
To build the view I used the UIKit interface builder, which allows you to insert elements such as images, buttons, etc. and which allows you to easily customize each element as well as its position and padding
However this is not enough to use them in a view, in fact with UIKit each view is managed by a ViewController.
You use view controllers to manage your UIKit app’s interface. A view controller manages a single root view, which may itself contain any number of subviews. User interactions with that view hierarchy are handled by your view controller, which coordinates with other objects of your app as needed. Every app has at least one view controller whose content fills the main window.
class ViewController: UIViewController {
@IBOutlet weak var mySwitch: UISwitch!
@IBOutlet weak var mySlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
Another difference are the IBActions, with which we can assign, for example, to a button, multiple actions when certain events occur
@IBAction func tapPoint(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: view)
print(location)
}
@IBAction func keyboardReturnText(_ sender: UITextField) {
if let text = sender.text{
print(text)
}
}
@IBAction func buttonTapped(_ sender: Any) {
print("Button was tapped!")
if mySwitch.isOn{
print("switch is on")
}else{
print("switch is off")
}
print("value of slider: \(mySlider.value)")
}
Then i’ve created the same view with the same functionality in SwiftUI, first I had to use a navigation controller to create a navigation between the views, then you need to add a UIHostingController with the interface builder and add a IBSegueAction inside the ViewController:
import SwiftUI
@IBSegueAction func mySwiftView(_ coder: NSCoder) -> UIViewController? {
return UIHostingController(coder: coder, rootView: SwiftUIVersionView())
}
And this is the same view with one single file in made with SwiftUI:
In this example we have a list of contacts that we take from our model. The app displays a list of contacts in a table view and allows the user to select a contact to view their details.
The ViewController is responsible for displaying the details of a selected contact. It has two UILabel objects to display the name and description of the contact. It also has a Contact object that is passed to it from the TableViewController when a contact is selected.
import UIKit
class ViewController: UIViewController {
var aContact: Contact?
@IBOutlet weak var myContactLabel: UILabel!
@IBOutlet weak var myDescription: UILabel!
required init?(coder: NSCoder, aContact: Contact?) {
self.aContact = aContact
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
myContactLabel.text = (aContact?.name ?? "Name") + " " + (aContact?.surname ?? "Surname")
myDescription.text = aContact?.description
}
}
The TableViewController is responsible for displaying the list of contacts in a table view. It has a UITableView object and an array of Contact objects that are used to populate the table view.
Difference with SwiftUI
SwiftUI is a modern framework for building user interfaces in Swift. It provides a declarative syntax for defining user interfaces, making it easier and more intuitive to build apps. Some of the differences between UIKit and SwiftUI are:
Although SwiftUI is a newer and more modern framework for building user interfaces in Swift, there are still some positive aspects of using UIKit instead:
Overall, while SwiftUI is becoming the preferred framework for building user interfaces in Swift, UIKit still has many positive aspects that make it a suitable choice for certain projects and applications.
When you build an app, you want to make sure it looks good on every iOS device. Xcode includes a powerful system called Auto Layout which makes it easy to build intricate interfaces that work on various screen sizes.
Auto Layout relies on constraints, or rules, to dynamically calculate the size and position of all views in a view hierarchy. So your interfaces will look and work the same—no matter what device your users have in their hands or how they’re holding it.
At the right of the bottom button bar is a set of tools for creating and managing constraints. To lock the button in the center of the screen, you’ll create two constraints that define the position of the button.
In this way the button will have the same position in every device, iphone and tablet, with all orientation.
Now assume you want the height of the button to always be 60, no matter the screen size or orientation of the device. Click the Add New Constraints button , the button immediately to the right of the Align tool. The popover displays a list of text fields and checkboxes to help you add constraints. Select the Height checkbox and adjust the value to 60. Click “Add 1 Constraint” to create the height constraint.
Finally i’ve create three different labels, two with the auto layout, and as you can see the last one will have some problems when the device change, or the orientation.
Note
In Progress, i will update the repo with more examples
Russo Giovanni M.
For educational purposes
MIT