gpt4 book ai didi

ios - 细化 Swift API GET 函数

转载 作者:行者123 更新时间:2023-11-28 07:40:17 27 4
gpt4 key购买 nike

我正在做一个练习项目,其中 iOS 应用程序打印来自 jsonplaceholder.typicode.com 的/posts 列表,当用户选择一个时,加载详细 View Controller 并显示有关该帖子的更多信息(作者和评论数)。

我为三个不同的端点发出了三个单独的 GET 请求,因为每个端点都需要不同的返回类型和不同的参数(或根本不需要)。

我想尽可能多地使用三者之间共有的代码,并将其放入一个新函数中以整理类,但我觉得我可以做更多的事情。

有没有办法让这些 Structs 的返回类型更通用,用一个 Switch 来确定将 json 响应映射到哪个?任何指导将不胜感激。

import UIKit

struct Post: Codable {
let userId: Int
let id: Int
let title: String
let body: String
}

struct Author: Codable {
let name: String
}

struct Comment: Codable {
let postId: Int
let id: Int
let name: String
let email: String
let body: String
}

enum Result<Value> {
case success(Value)
case failure(Error)
}

class APIManager {

static let sharedInstance = APIManager()

func getUrl(for path: String) -> URL {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "jsonplaceholder.typicode.com"
urlComponents.path = path

guard let url = urlComponents.url else { fatalError("Could not create URL from components") }

return url
}

func getPosts(completion: ((Result<[Post]>) -> Void)?) {
let url = getUrl(for: "/posts")

var request = URLRequest(url: url)
request.httpMethod = "GET"

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request) { (responseData, response, responseError) in
DispatchQueue.main.async {
if let error = responseError {
completion?(.failure(error))
} else if let jsonData = responseData {
let decoder = JSONDecoder()

do {
let posts = try decoder.decode([Post].self, from: jsonData)
completion?(.success(posts))
} catch {
completion?(.failure(error))
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
completion?(.failure(error))
}
}
}

task.resume()
}

func getAuthor(for userId: Int, completion: ((Result<String>) -> Void)?) {
let url = getUrl(for: "/users/\(userId)")

var request = URLRequest(url: url)
request.httpMethod = "GET"

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request) { (responseData, response, responseError) in
DispatchQueue.main.async {
if let error = responseError {
completion?(.failure(error))
} else if let jsonData = responseData {
let decoder = JSONDecoder()

do {
let author = try decoder.decode(Author.self, from: jsonData)
completion?(.success(author.name))
} catch {
completion?(.failure(error))
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
completion?(.failure(error))
}
}
}

task.resume()
}

func getComments(for postId: Int, completion: ((Result<[Comment]>) -> Void)?) {
let url = getUrl(for: "/posts/\(postId)/comments")

var request = URLRequest(url: url)
request.httpMethod = "GET"

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request) { (responseData, response, responseError) in
DispatchQueue.main.async {
if let error = responseError {
completion?(.failure(error))
} else if let jsonData = responseData {
let decoder = JSONDecoder()

do {
let comments = try decoder.decode([Comment].self, from: jsonData)
completion?(.success(comments))
} catch {
completion?(.failure(error))
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
completion?(.failure(error))
}
}
}

task.resume()
}
}

最佳答案

只需利用通用的 Result 类型:

class APIManager {

static let sharedInstance = APIManager()

private func getUrl(for path: String) -> URL {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "jsonplaceholder.typicode.com"
urlComponents.path = path

guard let url = urlComponents.url else { fatalError("Could not create URL from components") }

return url
}

private func postsURL() -> URL { return getUrl(for: "/posts") }
private func usersURL(for userId : Int) -> URL { return getUrl(for: "/users/\(userId)") }
private func commentsURL(for postId : Int) -> URL { return getUrl(for: "/posts/\(postId)/comments") }

func getPosts(completion: @escaping (Result<[Post]>) -> Void) {
getInfo(for: postsURL(), completion: completion)
}

func getAuthor(for userId: Int, completion: @escaping (Result<Author>) -> Void) {
getInfo(for: usersURL(for: userId), completion: completion)
}

func getComments(for postId: Int, completion: @escaping (Result<[Comment]>) -> Void) {
getInfo(for: commentsURL(for: postId), completion: completion)
}

private func getInfo<T: Decodable>(for url : URL, completion: @escaping (Result<T>) -> Void) {
let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
DispatchQueue.main.async {
if let error = error {
completion(.failure(error))
} else {
let decoder = JSONDecoder()
do {
let comments = try decoder.decode(T.self, from: data!)
completion(.success(comments))
} catch {
completion(.failure(error))
}
}
}
}
task.resume()
}
}

并使用它

let manager = APIManager.sharedInstance
manager.getAuthor(for: 1) { result in
switch result {
case .success(let author) : print(author.name)
case .failure(let error) : print(error)
}
}

关于ios - 细化 Swift API GET 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52447135/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com