使用 JSON 响应快速调用函数时出错

Posted

技术标签:

【中文标题】使用 JSON 响应快速调用函数时出错【英文标题】:error calling functions in swift with a JSON response 【发布时间】:2015-04-26 18:26:50 【问题描述】:

其他人可以帮助我知道哪种方法可以快速调用函数并接收 JSON 集合响应吗? 我在 viewController.swift 中调用 ApiClient().getList() 函数,该函数调用我的 API 并在 apiClient.swift 中接收 JSON 响应,最后我想将此 JSON 响应分配给 viewController 中的 self.result 变量。快。

我的代码是:

viewController.swift

import UIKit


class ClubsViewController: UIViewController, UITableViewDataSource

    var results: [JSON]? = []

    @IBOutlet var tableview:UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()
        self.loadClubsObjects()
    

    func loadClubsObjects()

        self.results = ApiClient().getList() <--- here is the call
        self.tableview.reloadData()

    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.results?.count ?? 0
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        var cell = tableView.dequeueReusableCellWithIdentifier("clubsObjectCell") as! ClubsTableViewCell
        cell.clubsObject = self.results?[indexPath.row]
        return cell
    

ApiClient.swift

import Foundation
import Alamofire

class ApiClient 

     func getList() -> [JSON] 

            var URL = NSURL(string: "https://api.com/v1/clubs")
            var mutableURLRequest = NSMutableURLRequest(URL: URL!)
            mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
            mutableURLRequest.HTTPMethod = "GET"
            mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")
            let manager = Alamofire.Manager.sharedInstance
            let request = manager.request(mutableURLRequest)
            request.responseJSON  (request, response, json, error) in

                if (json != nil)
                  var jsonObj = JSON(json!)
                  if let data = jsonObj["hits"].arrayValue as [JSON]?
                    return data

                  
                
            
     

apiClient.swift 中的错误是

返回数据 -> [JSON] 不能转换为 Void

【问题讨论】:

您的函数返回 Void。检查func getList(completion:(data: JSON?, error: NSError?) -&gt; Void) 无需进一步检查,此函数至少应返回 [JSON] 我刚刚更新了 getList() 函数,现在我只得到一个错误,返回数据 -> [JSON] 不能转换为 Void,我该如何解决这个问题? 替换 ->Void 为 -> [JSON] 【参考方案1】:

getList 的定义方式是它应该返回[JSON] 对象。但它不能这样做,因为responseJSON 是一个异步方法(即,直到您从getList 返回之后,才会调用responseJSON 的完成闭包)。

你必须使用你自己的completionHandler 模式。例如,getList 不会返回 anything,,而是会接受一个完成处理程序参数:

func getList(completionHandler: ([JSON]) -> ()) 
    let URL = NSURL(string: "https://api.com/v1/clubs")
    let mutableURLRequest = NSMutableURLRequest(URL: URL!)

    mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
    mutableURLRequest.HTTPMethod = "GET"
    mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")

    let manager = Alamofire.Manager.sharedInstance
    let request = manager.request(mutableURLRequest)

    request.responseJSON  response in
        if let json = response.result.value  
            var jsonObj = JSON(json)
            if let hits = jsonObj["hits"].arrayValue as [JSON]? 
                completionHandler(hits)
            
        
    

你会像这样调用它:

let apiClient = ApiClient()

func loadClubsObjects() 
    apiClient.getList()  hits in
        // use hits here

        self.results = hits
        self.tableView.reloadData()
    

    // but not here

注意,我倾向于不让 API 客户端成为 loadClubsObjects 的局部变量,而是如上所示的类属性。随心所欲,但我觉得它是一个更合乎逻辑的生命周期。


如果您想处理错误,您可以更改完成处理程序闭包,以便 (a) JSON 命中数组是可选的; (b) 添加一个可选的错误对象。然后更改getList 以传回这些可选值:

func getList(completionHandler: ([JSON]?, NSError?) -> ()) 
    let URL = NSURL(string: "https://api.com/v1/clubs")
    let mutableURLRequest = NSMutableURLRequest(URL: URL!)

    mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
    mutableURLRequest.HTTPMethod = "GET"
    mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")

    let manager = Alamofire.Manager.sharedInstance
    let request = manager.request(mutableURLRequest)

    request.responseJSON  response in
        if let json = response.result.value 
            var jsonObj = JSON(json)
            if let hits = jsonObj["hits"].arrayValue as [JSON]? 
                completionHandler(hits, nil)
             else 
                let jsonError = NSError(domain: "mydomain", code: MyErrorCode.HitsNotFound, userInfo: nil) // create whatever sort of error object you think is appropriate if `hits` was not found
                completionHandler(nil, jsonError)
            
         else 
            completionHandler(nil, response.result.error)
        
    

然后,当你调用它的时候,你可以检查JSON对象数组是否为nil,如果是nil,则查看NSError对象。

【讨论】:

非常感谢 Rob!,从响应中捕获错误的最佳方法是什么? 只需将带有NSError 对象的附加参数添加到完成处理程序,并确保即使出现错误也调用完成处理程序。我最初的版本试图尽可能忠实地反映您的原始实现,但是添加这样的错误处理是至关重要的。请参阅修改后的答案。

以上是关于使用 JSON 响应快速调用函数时出错的主要内容,如果未能解决你的问题,请参考以下文章

在JavaScript中使用/定义函数时出错

但回调方法出错 请检查自定义load回调函数是啥

为啥我不能内联调用 res.json?

为啥尝试使用显式类型参数调用模板成员函数时会出错?

在类函数中调用 Alamofire 时出错

尝试获取 json 响应时出错 [Flutter]