简体   繁体   English

如何让我的 iOS 应用程序连接到 api?

[英]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,那么,那将,

  • if there was a URLSession error, tell you what the error was;如果出现URLSession错误,请告诉您错误是什么;
  • if there was a non-2xx status code, tell you what the code was (and return the body of the response, too, in case you want to look at that);如果有非 2xx 状态代码,请告诉您代码是什么(并返回响应的主体,以防您想要查看); and
  • if there was a parsing error, tell you what the parsing error was.如果存在解析错误,请告诉您解析错误是什么。

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.

相关问题 当我的ios应用程序连接到互联网时,如何在不重新打开该应用程序的情况下刷新我的ios应用程序 - How can i refresh my ios app when my ios app get connected to the internet without re-opening the app 如何在我的应用程序中找到私有iOS API使用情况? - How can I find private iOS API usage in my app? 如何让Alexa在我的iOS应用程序上工作? - How can I get Alexa working on my iOS app? 如何让 Xcode 为 iOS 构建我的应用程序? - How can I get Xcode to build my app for iOS? iOS 如何获取连接的蓝牙设备的电池电量 - iOS How can I get the battery level of the connected bluetooth device 我错误地将我的iOS App(颤动)连接到错误的firebase项目,我可以更改firebase项目吗? - I've mistakenly connected my iOS App(flutter) to the wrong firebase project, can I change firebase projects? 如何在我的iOS应用程序中获得透明背景,以便我可以看到主屏幕壁纸? - How can I get a transparent background in my iOS app so I can see the Home Screen wallpaper? 每当用户从App Store购买我的iOS应用程序时,如何获得通知? - How can I get notified every time a user purchases my iOS app from the App Store? 如果当 iOS 应用程序在后台时 NSTimer 不起作用,我怎样才能让我的应用程序定期唤醒? - If NSTimer does not work when an iOS app is in the background, how can I get my app to wake up periodically? 我如何从Apple的应用程序内购买中获得报酬? (iOS iTunesConnect) - How can I get paid for my app's in-app purchase from Apple? (iOS iTunesConnect)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM