调用Web API时出错

时间:2014-06-20 17:43:47

标签: ios json swift

我们有几个SDK旨在让所有技能水平的开发人员尽可能轻松,包括最新手消费政府API(http://usdepartmentoflabor.github.io/DOLAPI/code.html#sdks)。我现在正试图在Swift上抢先一步,并且我在一个有一个目的的简单应用程序的上下文中开始使用它:证明SDK有效。

我遇到的麻烦是它因为我无法解释的原因而崩溃(完整来源是https://github.com/MikePulsiferDOL/test-app)。

import Foundation

protocol GovDataRequestProtocol {
    func didCompleteWithError(errorMessage: String)
    func didCompleteWithArray(results: NSArray)
}

class GovDataRequest {

    var delegate: GovDataRequestProtocol? = nil

    var activeRequests = Int[]()
    var APIKey = ""
    var APIHost = ""
    var APIURL = ""

    init(APIKey: String, APIHost: String, APIURL:String) {
        self.APIKey = APIKey
        self.APIHost = APIHost
        self.APIURL = APIURL
    }


    func callAPIMethod (#method: String, arguments: Dictionary<String,String>, timeOut: Double) {
        // Construct the base url based on the provided information
        var url = APIHost + APIURL + "/" + method
        // Start building the query string
        var queryString = ""

        // Where appropriate, add the key
        switch APIHost {
        case "http://api.dol.gov":
            queryString = "?KEY=" + APIKey
        case "http://api.census.gov", "http://pillbox.nlm.nih.gov":
            queryString = "?key=" + APIKey
        case "http://api.eia.gov", "http://developer.nrel.gov", "http://api.stlouisfed.org", "http://healthfinder.gov":
            queryString = "?api_key=" + APIKey
        case "http://www.ncdc.noaa.gov":
            queryString = "?token=" + APIKey
        default:
            // do nothing for now
            println("doing nothing for now")
        }

        //Construct the arguments part of the query string
        for (argKey, argValue) in arguments {
            switch APIHost {
            case "http://api.dol.gov":
                // DOL's V1 API has specific formatting requirements for arguments in the query string
                switch argKey {
                case "top", "skip", "select", "orderby", "filter":
                    queryString += "&$" + argKey + "=" + argValue
                case "format", "query", "region", "locality", "skipcount":
                    queryString += "&" + argKey + "=" + argValue
                default:
                    println("nothing to see here")
                }
            case "http://go.usa.gov":
                // go.usa.gov requires that the apiKey be the 2nd argument
                if countElements(queryString) == 0 {
                    queryString += "?" + argKey + "=" + argValue + "&apiKey=" + APIKey
                } else {
                    queryString += "&" + argKey + "=" + argValue
                }
            default:
                if countElements(queryString) == 0 {
                    queryString += "?" + argKey + "=" + argValue
                } else {
                    queryString += "&" + argKey + "=" + argValue
                }
            }

        }

        //If there are arguments, append them to the url
        if countElements(queryString) > 0 {
            url += queryString
        }

        //DOT FMCSA requires that the key be placed at the end.
        if APIHost == "https://mobile.fmcsa.dot.gov" {
            if countElements(queryString) > 0 {
                url += "&webKey=" + APIKey
            } else {
                url += "?webKey=" + APIKey
            }
        }

        /*
            ASSUMPTION: data retrieved is in JSON format.
            TODO: consider situation when XML is received.
        */

        // Send the request to the API and parse the JSON
        var urlToPackage = url.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
        println(urlToPackage)
        var urlToSend: NSURL = NSURL(string: urlToPackage)
        var session = NSURLSession.sharedSession()
        var request = NSMutableURLRequest(URL:urlToSend)
        //request.setTimeoutInterval(timeOut)
        request.addValue("application/json",forHTTPHeaderField:"Accept")
        var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
            println("Task completed")
            if(error) {
                // if there is an error in the request, print it to the console 
                //self.delegate?.didCompleteWithError("Error, Will Robinson")
                //println(error.localizedDescription)
                println("oops!")
            }
            var err: NSError?
            var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
            if(err?) {
                // If there is an error parson JSON, print it to the console
                NSLog ("Error parsing the JSON")
            }
            var results: NSArray = jsonResult["results"] as NSArray
            self.delegate?.didCompleteWithArray(results)
        })
        task.resume()
    }


}

查看控制器:

import UIKit

class ViewController: UIViewController, GovDataRequestProtocol {


    var firstRequest: GovDataRequest = GovDataRequest(APIKey: "", APIHost: "http://data.fcc.gov", APIURL: "/lpfmapi/rest/v1/lat/36")
    //var firstRequest: GovDataRequest = GovDataRequest(APIKey: "", APIHost: "https://itunes.apple.com", APIURL: "/search")

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.firstRequest.delegate = self
        //var arguments = Dictionary<String, String>()
        var arguments = ["format": "json", "secondchannel": "true"]
        //var arguments = ["term": "Angry Birds", "media": "software"]
        var timeOut = 60.0
        firstRequest.callAPIMethod(method: "long/-119", arguments: arguments, timeOut: timeOut)
        //firstRequest.callAPIMethod(method: "", arguments: arguments, timeOut: timeOut)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func didCompleteWithError (errorMessage: String) {
        NSLog("error")

    }

    func didCompleteWithArray (results:NSArray) {
        println("success!")
        //Let's see what we've got
        for item : AnyObject in results {
            if let oneItem = item as? NSDictionary {
                println("Dictionary!")
            } else {
                println("Not a Dictionary!")
            }

        }

    }
}

当我使用iTunes API进行测试时,它可以正常工作。如果我使用FCC,则它会在底部附近的代码的错误处理部分崩溃(EXC_BAD_INSTRUCTION(代码= EXCI386_INVOP,子代码= 0x0))。

如果我注释掉错误处理代码,它会在我发送请求的地方崩溃(在var任务...)。如您所见,我打印发送的URL(urlToPackage)。我接受了输出并将其输入到chrome中以验证URL是否正确形成。

想法?

由于

1 个答案:

答案 0 :(得分:0)

返回的JSON似乎没有results数组,所以这一行:

var results: NSArray = jsonResult["results"] as NSArray

获得nil&amp;炸毁。当我使用有效密钥替换results时,例如interferingAnalysis,您的示例代码就可以正常运行。