[英]How can I get my iOS app connected with api?
I am a beginner in iOS development.我是iOS开发的初学者。 I was trying to use an api URl: https://www.arbeitnow.com/api/job-board-api in my job search iOS app.
我试图在我的求职 iOS 应用程序中使用 api URl: https://www.arbeitnow.com/api/job-board-api 。 But nothing shows on my app.
但我的应用程序上没有显示任何内容。 I tested the URL in POSTMAN and it returns json(but HTML in description part?).
我在 POSTMAN 中测试了 URL,它返回 json(但在描述部分是 HTML?)。 I wrote the code:
我写了代码:
func getResults(completed: @escaping (Result<[Results], ErrorMessage>) -> Void) {
let urlString = "https://www.arbeitnow.com/api/job-board-api"
guard let url = URL(string: urlString) else {return}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let _ = error {
completed(.failure(.invalidData))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let deconder = JSONDecoder()
deconder.keyDecodingStrategy = .convertFromSnakeCase
let results = try deconder.decode([Results].self, from: data)
completed(.success(results))
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
}
struct Results: Codable {
let slug, companyName, title, resultsDescription: String
let remote: Bool
let url: String
let tags, jobTypes: [String]
let location: String
let createdAt: Int
enum CodingKeys: String, CodingKey {
case slug
case companyName = "company_name"
case title
case resultsDescription = "description"
case remote, url, tags
case jobTypes = "job_types"
case location
case createdAt = "created_at"
}
}
I used the code in HomeViewController:我使用了 HomeViewController 中的代码:
override func viewDidLoad() {
super.viewDidLoad()
title = "Home"
collectionView.backgroundColor = UIColor(named: "backgroundMain")
collectionView.register(SearchViewCell.self, forCellWithReuseIdentifier: cellId)
setupSearchBar()
Service.shared.getResults() { [weak self] result in
switch result {
case .success(let results):
print(results)
self?.jobResults = results
DispatchQueue.main.async {
self?.collectionView.reloadData()
}
case .failure(let error):
print(error)
}
}
}
888 888
I don't know what is wrong with my code.我不知道我的代码有什么问题。 Can anyone help?
谁能帮忙? Thanks!
谢谢!
You are discarding all meaningful error information, which will make this hard to diagnose.您正在丢弃所有有意义的错误信息,这将使诊断变得困难。 If you get an
Error
object, you should return that:如果您收到
Error
object,您应该返回:
enum WebServiceError: Error {
case httpError(Data, Int)
}
func getResults(completion: @escaping (Result<[Results], Error>) -> Void) {
let urlString = "https://www.arbeitnow.com/api/job-board-api"
guard let url = URL(string: urlString) else {
completion(.failure(URLError(.badURL)))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else {
completion(.failure(error ?? URLError(.badServerResponse)))
return
}
guard 200 ..< 300 ~= response.statusCode else {
completion(.failure(WebServiceError.httpError(data, response.statusCode)))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let results = try decoder.decode([Results].self, from: data)
completion(.success(results.data))
} catch {
completion(.failure(error))
}
}
task.resume()
}
So, that will,那么,那将,
URLSession
error, tell you what the error was;URLSession
错误,请告诉您错误是什么; Without something like this, that captures the salient error information, you are flying blind.如果没有这样的东西来捕获显着的错误信息,你就是在盲目飞行。
In this case, the error is that you are parsing for [Results]
, but the structure is a dictionary, whose key is data
and whose value is a [Results]
.在这种情况下,错误是您正在解析
[Results]
,但结构是一个字典,其键是data
,其值是[Results]
。 You are missing an object for this dictionary that wraps the [Results]
.您缺少包含
[Results]
的字典的 object。
struct ResponseObject: Decodable {
let data: [Posting]
let links: Links
let meta: Meta
}
struct Posting: Decodable {
let slug, companyName, title, description: String
let remote: Bool
let url: String
let tags, jobTypes: [String]
let location: String
let createdAt: Int
}
struct Links: Decodable {
let first: URL?
let last: URL?
let prev: URL?
let next: URL?
}
struct Meta: Decodable {
let currentPage: Int
let path: URL
let perPage: Int
let from: Int
let to: Int
let terms: String
let info: String
}
func getResults(completion: @escaping (Result<[Posting], Error>) -> Void) {
let urlString = "https://www.arbeitnow.com/api/job-board-api"
guard let url = URL(string: urlString) else {
completion(.failure(URLError(.badURL)))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else {
completion(.failure(error ?? URLError(.badServerResponse)))
return
}
guard 200 ..< 300 ~= response.statusCode else {
completion(.failure(WebServiceError.httpError(data, response.statusCode)))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let results = try decoder.decode(ResponseObject.self, from: data)
completion(.success(results.data))
} catch {
completion(.failure(error))
}
}
task.resume()
}
Your model does not match the JSON you receive from the link you provided:您的 model 与您从提供的链接收到的 JSON 不匹配:
Using:使用:
struct Root: Codable{
let data: [WorkData]
let links: Links
let meta: Meta
}
// MARK: - Links
struct Links: Codable {
let first: String
let last, prev: String?
let next: String
}
// MARK: - Meta
struct Meta: Codable {
let currentPage, from: Int
let path: String
let perPage, to: Int
let terms, info: String
enum CodingKeys: String, CodingKey {
case currentPage = "current_page"
case from, path
case perPage = "per_page"
case to, terms, info
}
}
struct WorkData: Codable {
let slug, companyName, title, payloadDescription: String
let remote: Bool
let url: String
let tags, jobTypes: [String]
let location: String
let createdAt: Int
enum CodingKeys: String, CodingKey {
case slug
case companyName = "company_name"
case title
case payloadDescription = "description"
case remote, url, tags
case jobTypes = "job_types"
case location
case createdAt = "created_at"
}
}
should solve the problem应该解决问题
Usage:用法:
let root = JsonDecoder().decode(Root.self, from: data)
let firstCompany = root.data[0]
Edit to adress the comment: This should work!编辑以解决评论:这应该有效!
let results = try decoder.decode([Results].self, from: data)
let results = try decoder.decode([Results].self, from: 数据)
is your code isn´t it?是你的代码不是吗?
instead use:而是使用:
let root = JsonDecoder().decode(Root.self, from: data)
how could data be missing here?数据怎么会在这里丢失?
After that you should either map the root object to your Result
type to keep your Viewmodel and completion Handler the way they are now.之后,您应该 map 根 object 到您的
Result
类型,以保持您的 Viewmodel 和完成处理程序保持现在的状态。 Or change Viewmodel and completion Handler instead.或者改为更改 Viewmodel 和完成处理程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.