Exercise 1: createTask(_:) — A Real POST Request with JSON Body and Response Decoding — Possible Solution ================================================================================================================== func createTask(_ newTask: NewTaskRequest) async throws -> Task { let url = URL(string: "https://api.example.com/tasks")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try JSONEncoder().encode(newTask) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, (200..<300).contains(httpResponse.statusCode) else { throw APIError.requestFailed(statusCode: (response as? HTTPURLResponse)?.statusCode ?? 0) } do { return try JSONDecoder().decode(Task.self, from: data) } catch { throw APIError.decodingFailed } } HOW IT WORKS: A real URLRequest is built with httpMethod set to "POST" (rather than the implicit GET a plain URL would use), a real "Content-Type: application/json" header telling the server what format the body is in, and httpBody set to the JSON-encoded bytes of newTask via JSONEncoder().encode(newTask) - exactly the chapter's own Encodable pattern, applied to the specific NewTaskRequest struct passed into this function. URLSession.shared.data(for: request) - the request-based overload, not the URL-based data(from:) Fundamentals used - sends the fully configured request, including its method, header, and body. The response is checked against the real 200..<300 success range (per the chapter's own reasoning that a real server might return 200, 201, or another 2xx code, not only exactly 200), throwing a real, specific APIError.requestFailed with the actual status code on failure. On success, the response body - presumably the newly created task, echoed back by the server with its own assigned real id - is decoded into a Task using the same JSONDecoder/do-catch/decodingFailed pattern established elsewhere in this chapter. ANSWER: createTask(_:) builds a real POST URLRequest with a JSON- encoded body via JSONEncoder, sends it with URLSession.shared.data(for:), checks the real 200..<300 success range, and decodes the server's response into a Task - correctly combining this chapter's own Encodable, URLRequest, and error-handling patterns into one complete networking function. WHY THIS WORKS AS AN ANSWER ------------------------------ This correctly assembles every real technique the chapter covered (URLRequest configuration, Encodable body encoding, range-based status checking, and structured error throwing) into one cohesive, real POST function.