translation
www.hackingwithswift.com/books/ios-s…
For more content, please follow the public account “Swift Garden”.
Like articles? How about a 🔺💛➕ triple? Follow the column, follow me 🚀🚀🚀
Send and receive orders over the network
IOS has great built-in features for handling network requests, especially the URLSession class that makes sending and receiving data fairly easy. Combined with Codable, we convert between Swift objects and JSON, and with URLRequest, which allows us to configure exactly what data to send, we can do cool things in less than 20 lines of code.
First, we create a method to call when the Place Order button is clicked — add the following method to the CheckoutView:
func placeOrder(a){}Copy the code
Then change the Place Order button to look like this:
Button("Place Order") {
self.placeOrder()
}
.padding()Copy the code
In the placeOrder() method, we need to do three things:
- The current
order
Object to JSON data for sending - Accurate a
URLRequest
, used to encode JSON data - Run the request and process the response
The first step is straightforward, as we have made the Order class compliant with the Codable protocol, so we can archive it with JSONEncoder, adding the following code to placeOrder() :
guard let encoded = try? JSONEncoder().encode(order) else {
print("Failed to encode order")
return
}Copy the code
The second step — preparing the URLRequest to send our data — requires more thought. Think about it, we need to send the data to the server in a certain way so that it can be processed correctly, which means we need to provide two additional fields in addition to the order:
- The HTTP method that determines how data is sent. There are several HTTP methods, but in practice only GET (” I want to read data “) and POST (” I want to write data “) are the most commonly used. We want to write data here, because we’re using the POST method.
- The content type of the request determines the type of data being sent, which affects how the server treats the data. This is determined by the MIME type, which was originally designed to be used for sending E-mail attachments, and which has a very wide range of options.
So, the next part of the code for placeOrder() is to create a URLRequest and configure it to send JSON data with the HTTP POST method, and attach our data.
Of course, the real question is where do we send our requests, and I don’t think we’re going to build your own Web server for this tutorial. For this reason, we use a very useful website called Reqres.in, which allows us to send arbitrary data and send it back automatically. For networking prototypes, this is great because you get actual data feedback based on whatever data you send.
Add the following code to placeOrder() :
let url = URL(string: "https://reqres.in/api/cupcakes")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = encodedCopy the code
Note that here I added a forced unpack to the URL(string:) constructor. Creating a URL based on strings can fail because you might pass in an unreliable URL string, but here I typed the URL in hand with confidence — the lack of string interpolation in the header can cause problems.
Here, the network request has been set up, we should use it for URLSession. Shared. DataTask (), and we just created the URL of the request. Remember, if you forget to call resume() on the dataTask, it won’t start. This is why every time I write a task, I always write a call to Resume before filling in the method body.
Next, add the following method to placeOrder() :
URLSession.shared.dataTask(with: request) { data, response, error in
// handle the result here.
}.resume()Copy the code
Then comes the most important part: we need to read the result of the request. If there is an error – such as no network connection – we print the message and return it.
Add the following method to placeOrder() :
guard let data = data else {
print("No data in response: \(error? .localizedDescription ?? "Unknown error").")
return
}Copy the code
If the guard statement above passes, it means that we got some data from the server. Because we used reqres.in, we actually got the data of the same order we sent. Therefore, we can use the JSONDecoder to decode JSON back into the object.
To confirm that everything is working, we need to display an alert with the order details. This order should be exactly the same as the one we sent, otherwise there is an error in our code.
To display an alert, we need to use the properties to store the message, and whether to display the tag. Add the following two properties to the CheckoutView:
@State private var confirmationMessage = ""
@State private var showingConfirmation = falseCopy the code
Add the following modifier to CheckoutView’s GeometryReader:
.alert(isPresented: $showingConfirmation) {
Alert(title: Text("Thank you!"), message: Text(confirmationMessage), dismissButton: .default(Text("OK")))}Copy the code
Next we complete the network code: we need to decode the returned data, set the message with the decoded data, and then set showingConfirmation to true for alert to display. If the decoding fails — for example, if the server returns something other than an order for some reason — we can print an error message.
Add the final code to placeOrder() and place it in the completion closure of dataTask(with:) :
if let decodedOrder = try? JSONDecoder().decode(Order.self, from: data) {
self.confirmationMessage = "Your order for \(decodedOrder.quantity)x \(Order.types[decodedOrder.type].lowercased()) cupcakes is on its way!"
self.showingConfirmation = true
} else {
print("Invalid response from server")}Copy the code
With the network code complete, the application is virtually complete. To try running the code, you can select the cake, enter the shipping information, and click Place Order to see the Alert display.
To finish.
My official account here is Swift and computer programming related articles, as well as excellent foreign article translation, welcome to follow ~