0
0
iOS Swiftmobile~20 mins

GET request with async/await in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Simple GET Request
This screen fetches a random joke from an online API and shows it on the screen when you tap the button.
Target UI
-------------------------
| Simple GET Request     |
|-----------------------|
|                       |
|  [ Joke will appear   ]|
|  [ here after fetch ]  |
|                       |
|  [ Fetch Joke Button ] |
-------------------------
Add a button labeled 'Fetch Joke' at the bottom center.
When tapped, perform an async GET request to https://official-joke-api.appspot.com/random_joke.
Parse the JSON response to get the joke's setup and punchline.
Display the joke text in the center area.
Show a loading indicator while fetching.
Handle errors by showing an alert with a friendly message.
Starter Code
iOS Swift
import SwiftUI

struct ContentView: View {
    @State private var jokeText = "Press the button to fetch a joke."
    @State private var isLoading = false
    @State private var showAlert = false
    @State private var alertMessage = ""

    var body: some View {
        VStack {
            Spacer()
            Text(jokeText)
                .multilineTextAlignment(.center)
                .padding()
            Spacer()
            if isLoading {
                ProgressView()
                    .padding()
            }
            Button("Fetch Joke") {
                // TODO: Add async GET request here
            }
            .padding()
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Error"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Solution
iOS Swift
import SwiftUI

struct Joke: Decodable {
    let setup: String
    let punchline: String
}

struct ContentView: View {
    @State private var jokeText = "Press the button to fetch a joke."
    @State private var isLoading = false
    @State private var showAlert = false
    @State private var alertMessage = ""

    var body: some View {
        VStack {
            Spacer()
            Text(jokeText)
                .multilineTextAlignment(.center)
                .padding()
            Spacer()
            if isLoading {
                ProgressView()
                    .padding()
            }
            Button("Fetch Joke") {
                Task {
                    await fetchJoke()
                }
            }
            .padding()
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Error"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
        }
    }

    func fetchJoke() async {
        isLoading = true
        defer { isLoading = false }

        guard let url = URL(string: "https://official-joke-api.appspot.com/random_joke") else {
            alertMessage = "Invalid URL."
            showAlert = true
            return
        }

        do {
            let (data, response) = try await URLSession.shared.data(from: url)

            guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
                alertMessage = "Server error."
                showAlert = true
                return
            }

            let joke = try JSONDecoder().decode(Joke.self, from: data)
            jokeText = "\(joke.setup)\n\n\(joke.punchline)"
        } catch {
            alertMessage = "Failed to fetch joke. Please try again."
            showAlert = true
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

This solution uses SwiftUI with async/await to fetch a joke from the API.

We define a Joke struct matching the JSON fields setup and punchline.

The fetchJoke() function is marked async and uses URLSession.shared.data(from:) with await to perform the GET request.

We check the HTTP response code to ensure success, then decode the JSON data into a Joke instance.

The joke text is updated on the main thread by changing the jokeText state variable.

Loading state is managed with isLoading to show a spinner while fetching.

Errors show an alert with a friendly message.

The button triggers the async fetch inside a Task to run asynchronously.

Final Result
Completed Screen
-------------------------
| Simple GET Request     |
|-----------------------|
|                       |
|  Why did the chicken  |
|  cross the road?      |
|                       |
|  To get to the other  |
|  side!                |
|                       |
|  [ Fetch Joke Button ] |
-------------------------
User taps 'Fetch Joke' button.
A spinner appears below the joke text while loading.
After a moment, the joke text updates with the fetched joke.
If an error occurs, an alert pops up with an error message.
Stretch Goal
Add a pull-to-refresh gesture to fetch a new joke.
💡 Hint
Use SwiftUI's .refreshable modifier on the VStack and call fetchJoke() inside it.