- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在做一个练习项目,其中 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/
我正在尝试缩小此图像,但它会不断失真。 这是我应用细化的相关代码。我也尝试过使用“thin”功能而不是“skeletonize”,但结果相似。 from skimage.morphology impo
好的,据我所知,目前我们有两种方法 首先是我可以在给定脚本中使用的一些 javascript。但这会关闭所有内容的右键单击。 window.oncontextmenu = function() {
在 MarkLogic 中如何找到元素所在的文档 URI 匹配的值为1742 这里是示例 XML 文档: 1742 1742 TT 1742
摘要:我有一个数据集,其收集方式使得维度最初不可用。我想获取本质上是一大块无差别的数据,并为其添加维度,以便可以对其进行查询、子集化等。这是以下问题的核心。 这是我拥有的 xarray 数据集: D
我有一个大型数据集(请参阅下面的示例格式),我需要进行以下思考: 确定第 1、2、5 列中出现的重复值 - 如果全部重复,那么我需要删除多余的行并对第 8 列中的值进行平均(这对于我将发布的代码是成功
我正在做一个练习项目,其中 iOS 应用程序打印来自 jsonplaceholder.typicode.com 的/posts 列表,当用户选择一个时,加载详细 View Controller 并显示
module Access def last self[-1] end def start_end self[0] + last end end module Stri
我是一名优秀的程序员,十分优秀!