…start there, instead of at the welcome screen. You’ll also learn about how to store data in Swift dictionaries and realize that string manipulation is complicated. Data Persistence Depending on what type of data you’re saving, there are different ways of persisting your data: UserDefaults: Use this…
iOS & Swift
Chapter in SwiftUI Apprentice
Downloading Data
Feb 24 2025 · Chapter
…simple download tasks in TheMet, you’ll use the built-in shared session, which provides a reasonable default behavior. Create a URL from a String like https://metmuseum.org. This could fail — for example, if the string is empty. Create a URLRequest from this URL: This object contains the HTTP method…
iOS & Swift
Chapter in SwiftUI Apprentice
Prototyping the Main View
Feb 24 2025 · Chapter
…five Text subviews, duplicate the Text(exerciseNames[index]) view, edit the second view to Text("Video player"), then duplicate this line and edit the strings to create this list: VStack { Text(exerciseNames[index]) Text("Video player") Text("Timer") Text("Start/Done button") Text("Rating") Text("History button") } Xcode Tip: Embed…
iOS & Swift
Chapter in SwiftUI Apprentice
Lists & Navigation
Feb 24 2025 · Chapter
…there’s more to see. Note: When the label is only text, NavigationLink has a convenience initializer that creates a Text view from a String. ➤ In Live Preview, tap an item: Navigation link to ObjectView ContentView is currently the only view in the navigation stack. When you tap a list…
iOS & Swift
Chapter in SwiftUI Apprentice
Managing Data With Property Wrappers
Feb 24 2025 · Chapter
HistoryStore from ContentView to HIITFitApp to initialize it with or without saved history data. ThingStore has the property things, which is an array of String values. Like the HistoryStore in the first version of HIITFit, it’s a structure. In this chapter, you’ll first manage changes to the ThingStore…
iOS & Swift
Chapter in SwiftUI Apprentice
Prototyping Supplementary Views
Feb 24 2025 · Chapter
…short, medium, long and full, described in links from the developer documentation page for DateFormatter.Style. You can also specify your own format as a String. ➤ Open DateExtension.swift. The first method shows how to use a DateFormatter. func formatted(as format: String) -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = format return dateFormatter.string…
iOS & Swift
Chapter in SwiftUI Apprentice
Adding Photos to Your App
Feb 24 2025 · Chapter
…flexible protocol that allows you to describe how to import and export any types. Some existing data types, such as Data, which is a string of bytes, already conform to Transferable. When you add photos, these will be of type UIImage, which unfortunately does not conform. You’ll overcome…
iOS & Swift
Chapter in SwiftUI Apprentice
Saving Files
Feb 24 2025 · Chapter
…decode data to and from external files. ➤ Open CardsApp.swift and add this code to the end of the file: struct Team: Codable { let names: [String] let count: Int } let teamData = Team( names: [ "Richard", "Libranner", "Caroline", "Audrey", "Ray" ], count: 5) After you’ve seen how Codable works, you’ll delete this…
iOS & Swift
Chapter in SwiftUI Apprentice
Saving History Data
Feb 24 2025 · Chapter
Supply a button with an optional action. As well as the title you can provide a message that shows under the title. Surround the string with three """ to format your Text string on multiple lines. ➤ Build and run. Instead of seeing the failure message in the console…
iOS & Swift
Chapter in SwiftUI Apprentice
Widgets
Feb 24 2025 · Chapter
…body: some Widget { TheMetWidget() } } ➤ Open TheMetWidget.swift, then find TheMetWidget and edit the last two modifiers: configurationDisplayName(_:) and description(_:). struct TheMetWidget: Widget { // 1 let kind: String = "TheMetWidget" var body: some WidgetConfiguration { StaticConfiguration( kind: kind, provider: Provider() // 2 ) { entry in if #available(iOS 17.0, *) { TheMetWidgetEntryView(entry: entry) // 3 .containerBackground(.fill.tertiary, for: .widget…
iOS & Swift
Chapter in SwiftUI Apprentice
Just Enough Web Stuff
Feb 24 2025 · Chapter
Object Notation) is the most common data format used for HTTP communication by app clients. It’s a structured data format consisting of numbers, strings, and arrays and dictionaries that can contain strings, numbers and nested arrays and dictionaries. Web forms use form-encoded, which looks like a query string…
iOS & Swift
Chapter in SwiftUI Apprentice
Outlining a Photo Collage App
Feb 24 2025 · Chapter
HStack containing a button that will change the modal state. Because the text label for the button is a custom view, rather than a string, you use the Button(action:label:) initializer. You’ll add more toolbar items in a moment to this HStack. ➤ Fix the preview to send…
iOS & Swift
Chapter in SwiftUI Apprentice
Working With Datasets
Feb 24 2025 · Chapter
Documents URL. Tap the History button to see the sample data. Sample data In the console, you’ll see error messages: ForEach<Array, String, Text>: the ID Burpee occurs multiple times within the collection, this will give undefined results!. The error means that you are displaying non-unique…
iOS & Swift
Chapter in SwiftUI Apprentice
Adding Assets to Your App
Feb 24 2025 · Chapter
…needed. This is called lazy loading. ➤ In StickerModal, create a new type method to load the sticker names: static func loadStickers() -> [String] { var themes: [URL] = [] var stickerNames: [String] = [] } You’ll first load the folder names in the top level in the Stickers folder. These will be themes…
iOS & Swift
Chapter in SwiftUI Apprentice
Moving Data Between Views
Feb 24 2025 · Chapter
…background. Light mode 2.circle and 2.circle.fill ➤ In HeaderView.swift, replace the contents of HeaderView with the following code: @Binding var selectedTab: Int // 1 let titleText: String var body: some View { VStack { Text(titleText) .font(.largeTitle) HStack { // 2 ForEach(Exercise.exercises.indices, id: \.self) { index in // 3 let fill = index == selectedTab ? ".fill" : "" Image(systemName…
iOS & Swift
Chapter in SwiftUI Apprentice
Planning a Paged App
Feb 24 2025 · Chapter
Welcome!: The text changes in the canvas, too. Editing the view in the code also changes the canvas. A Text view simply displays a string of characters. It’s useful for listing the views you plan to create, as a kind of outline. You’ll use multiple Text views…
iOS & Swift
Chapter in SwiftUI Apprentice
Delightful UX — Final Touches
Feb 24 2025 · Chapter
…default “Hello World” from SplashScreen. Hello, World ➤ Open SplashScreen.swift and add this new method to SplashScreen: func card(letter: String, color: String) -> some View { ZStack { RoundedRectangle(cornerRadius: 25) .shadow(radius: 3) .frame(width: 120, height: 160) .foregroundStyle(.white) Text(letter) .fontWeight(.bold) .scalableText() .foregroundStyle(Color(color)) .frame(width…
iOS & Swift
Chapter in SwiftUI Apprentice
Checking Your Tools
Feb 24 2025 · Chapter
…modifiers display a globe symbol. You’ll learn about the Image view in Chapter 3, “Prototyping the Main View”. Text("Hello, world!") displays the string “Hello, world!”. ➤ Click the Selectable button below the preview canvas, then click the Text view in the canvas and select the Quick Help inspector. Text…
iOS & Swift
Chapter in SwiftUI Apprentice
Structures, Classes & Protocols
Feb 24 2025 · Chapter
…your card element data in this way: class CardElement { var transform: Transform } class ImageElement: CardElement { var image: Image? } class TextElement: CardElement { var text: String? } Here you have a base class CardElement with two sub-classes inheriting from CardElement. ImageElement and TextElement both inherit the transform property, but each type…
iOS & Swift
Chapter in SwiftUI Apprentice
Observing Objects
Feb 24 2025 · Chapter
…particular, when ExerciseView adds an ExerciseDay to exerciseDays, HistoryView gets updated. ➤ Now, add the following method to HistoryStore, below init(): func addDoneExercise(_ exerciseName: String) { let today = Date() if today.isSameDay(as: exerciseDays[0].date) { // 1 print("Adding \(exerciseName)") exerciseDays[0].exercises.append(exerciseName) } else { exerciseDays.insert( // 2 ExerciseDay(date: today, exercises: [exerciseName…