我來自 javascript,現在我正在為 swift 學習。我想列印我的 URLSession 回傳的一項,但我不知道該怎么做。
我的代碼:
import Foundation
import Dispatch
enum ServiceError: Error {
case invalidURL
case decodeFail(Error)
case network(Error?)
}
struct Address: Codable {
let zipcode: String
let address: String
let city: String
let uf: String
let complement: String?
enum CodingKeys: String, CodingKey {
case zipcode = "cep"
case address = "logradouro"
case city = "localidade"
case uf
case complement = "complemento"
}
}
class Service {
private let baseURL = "https://viacep.com.br/ws"
func get(cep: String, callback: @escaping (Result<Any, ServiceError>) -> Void) {
let path = "/\(cep)/json"
guard let url = URL(string: baseURL path) else {
callback(.failure(.invalidURL))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
callback(.failure(.network(error)))
return
}
guard let json: Address = try? JSONDecoder().decode(Address.self, from: data) else {
return
}
callback(.success(json))
}
task.resume()
}
}
do {
let service = Service()
service.get(cep: "1231234") { result in
DispatchQueue.main.async {
switch result {
case let .failure(error):
print(error)
case let .success(data):
print(data)
}
}
}
}
這是我的回報:
地址(郵編:“12341231”,地址:“Teste”,城市:“Teste”,uf:“TE”,補碼:可選(“”))
我想要我的回報是這樣的:
print(data.zipcode)
Output: 12341231
uj5u.com熱心網友回復:
與 javascript 不同,Swift 是強型別的,所以Address從你的回傳型別func get(cep:...),而不是Any.
請注意,在執行服務器請求時需要處理許多型別的錯誤。
錯誤可能意味著由于請求錯誤而無法解碼回應,例如 cep: "1231234" 的情況。如果您使用 cep:"01001000",則不會出現錯誤,并且一切正常。
因此,我建議更新您的代碼(尤其是ServiceError),以應對您可能遇到的各種錯誤。
這是我用來測驗答案的代碼:
let service = Service()
// try also "01001000" for no errors
service.get(cep: "1231234") { result in
switch result {
case let .failure(error):
print("\n---> error: \(error)")
case let .success(data):
print("\n---> data: \(data)")
print("---> zipcode: \(data.zipcode)")
}
}
和
class Service {
private let baseURL = "https://viacep.com.br/ws"
// here return Address, not Any
func get(cep: String, callback: @escaping (Result<Address, ServiceError>) -> Void) {
let path = "/\(cep)/json"
guard let url = URL(string: baseURL path) else {
callback(.failure(.invalidURL))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
callback(.failure(.network(error)))
return
}
// this shows you what the server is really sending you
print("\n---> data: \(String(data: data, encoding: .utf8)) \n")
guard let httpResponse = response as? HTTPURLResponse else {
callback(.failure(.apiError(reason: "Unknown")))
return
}
switch httpResponse.statusCode {
case 400: return callback(.failure(.apiError(reason: "Bad Request")))
case 401: return callback(.failure(.apiError(reason: "Unauthorized")))
case 403: return callback(.failure(.apiError(reason: "Resource forbidden")))
case 404: return callback(.failure(.apiError(reason: "Resource not found")))
case 405..<500: return callback(.failure(.apiError(reason: "client error")))
case 500..<600: return callback(.failure(.apiError(reason: "server error")))
default:
callback(.failure(.apiError(reason: "Unknown")))
}
// here use a proper do/catch
do {
let address = try JSONDecoder().decode(Address.self, from: data)
callback(.success(address))
} catch {
// could not be decoded as an Address.
callback(.failure(.decodeFail(error)))
}
}
task.resume()
}
}
enum ServiceError: Error {
case invalidURL
case decodeFail(Error)
case network(Error?)
case apiError(reason: String) // <-- here
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/529447.html
