Now that we have spent some time writing iOS applications using storyboards and Interface Builder we are going to take a look at a second method for writing apps. This method is the SwiftUI framework, which was introduced by Apple in 2018.
In SwiftUI we no longer use a graphical design tool to layout all of views for our apps. Instead, SwiftUI does everything in code. SwiftUI uses a declarative coding style in which we write code that sets up the user interface. At first this may seem inferior to using Interface Builder, since code is generally harder to write than just using a graphical design tool. As we will see, doing everything in code actually works pretty well, since both the code to set up the interface elements and the code for things like action methods are all going to appear together in the same place.
To get started using SwiftUI, start by making a new project for a new app. The one change you will need to make when setting up the app is to choose SwiftUI for the app's interface in place of Storyboard when you do the project setup.
When the project opens you will see the code for the app's view class:
import SwiftUI struct ContentView: View { var body: some View { Text("Hello, world!") .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Here are some things to note about this code:
ContentView
, that inherits from the SwiftUI View struct.body
property. This is a computed property: the code to compute the body for the view appears in the curly braces.For our second example I am going to construct a simple "Hello, World" application in SwiftUI that includes several elements in the user interface, including a button with an associated action.
Here is the complete code for that example.
import SwiftUI struct ContentView: View { @State var greeting : String = "Hello" var body: some View { VStack { Button("Greet Me") { greeting = "Hello, World!" }.buttonStyle(.borderedProminent) Spacer() Text(greeting) Spacer() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
As you can see, the only thing that has changed in this example is the code for the body property in the view.
Here are some things to notice about this code:
greeting
property. This property is annotated with the @State
property modifier. If you attach this modifier to a property and subsequently change the value of the property, the view will get rebuilt.Here again is part of the code for the button:
Button("Greet Me") { greeting = "Hello, World!" }
The code in the curly braces is actually code for a closure. This closure is essentially an anonymous function that the system will execute when the user clicks on the button. The closure in this example is what is know as a trailing closure: the code above is actually equivalent to this code:
Button("Greet Me",{greeting = "Hello, World!"})
This code sets up a closure and passes it as the second parameter to an initializer for the button.