Swift: Networking: Simple Request with Query
This article builds on $linktoid[art_0017]$.
Performing network communication in Swift is enabled using URLSession. A very simple request can be implemented with the asynchronous method `data(from: URL)` using just a couple of code lines.
Parameters for the request can be sent with query parameters. Use `URLComponents` and `URLQueryItem` for that. These types handle conversion of special characters and save you from implementing complicated checks of edge cases.
For easy testing the Python package FastAPI provides a very simple and quick means. That way handling network requests can be tested in the simulator while the server can be started on the developer computer.
Preparing a FastAPI Server
To handle query parameters one can declare function arguments. They are automatically treated as query parameters by FastAPI. For this test the function just returns an upper-cased string of the argument.
@app.get("/text/upcase")
def read_text_upcase(string: str):
return {"result": string.upper()}
Performing the Network Request in Swift
To add the query parameter to the URL, use `URLComponents` and `URLQueryItem` like shown below. It is strongly recommended to not add the query parameters using direct string manipulation of the URL.
import SwiftUI
struct SimpleRequestWithQueryView: View {
@State private var text: String = "a text"
@State private var response: String = "-"
@State private var errorInfo: String = "-"
var body: some View {
VStack {
Text("Simple Request with Query")
.font(.largeTitle)
Form {
TextField("Enter text", text: $text)
Button(action: {
sendRequest()
}, label: {
Label("Send", systemImage: "paperplane")
})
LabeledContent("Response", value: response)
LabeledContent("Error Info", value: errorInfo)
}
}
}
private func sendRequest() {
Task {
do {
guard let url = URL(string: "http://localhost:8000/text/upcase") else { return }
guard var comps = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
let qi = URLQueryItem(name: "string", value: text)
comps.queryItems = [qi]
guard let urlq = comps.url else { return }
let (data, resp) = try await URLSession.shared.data(from: urlq)
if let httpResp = resp as? HTTPURLResponse {
if httpResp.statusCode != 200 {
self.errorInfo = "Error: Expected 200"
return
}
}
guard let string = String(data: data, encoding: .utf8) else { return }
self.response = string
self.errorInfo = "-"
} catch {
self.response = "-"
self.errorInfo = "\(error.localizedDescription)"
}
}
}
}
#Preview {
SimpleRequestWithQueryView()
}