如何使用 AlamoFire 和 Swift 将 JSON 数据放入 UILabel

Posted

技术标签:

【中文标题】如何使用 AlamoFire 和 Swift 将 JSON 数据放入 UILabel【英文标题】:How can I put JSON data into a UILabel using AlamoFire and Swift 【发布时间】:2016-07-26 00:18:10 【问题描述】:

我正在尝试将 JSON Yahoo api 中的一些数据放入一些 UILabel 中。 当我尝试运行我的项目时,我遇到了 Thread 1 错误。

这是我的一些代码:

@IBOutlet weak var tableView: UITableView!
var stockSymbol: String = "AAPL"
var stock: [Stock] = []

override func viewDidLoad() 
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.registerNib(UINib(nibName: "HomeCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: "homeCell")
    tableView.rowHeight = 60

    // Do any additional setup after loading the view.
    SwiftStockKit.fetchStockForSymbol(symbol: stockSymbol)  (stock) -> ()  in
    self.stock = [stock]
        self.tableView.reloadData()


    


class func fetchStockForSymbol(symbol symbol: String, completion:(stock: Stock) -> ()) 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) 

        let stockURL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json"

        Alamofire.request(.GET, stockURL).responseJSON  response in

            if let resultJSON = response.result.value as? [String : AnyObject]  

                if let stockData = ((resultJSON["query"] as! [String : AnyObject])["results"] as! [String : AnyObject])["quote"] as? [String : AnyObject] 

                    // lengthy creation, yeah
                    var dataFields = [[String : String]]()
                    dataFields.append(["Ask" : stockData["Ask"] as? String ?? "N/A"])
                    dataFields.append(["Average Daily Volume" : stockData["AverageDailyVolume"] as? String ?? "N/A"])
                    dataFields.append(["Bid" : stockData["Bid"] as? String ?? "N/A"])
                    dataFields.append(["Book Value" : stockData["BookValue"] as? String ?? "N/A"])
                    dataFields.append(["Change" : stockData["Change"] as? String ?? "N/A"])
                    dataFields.append(["Percent Change" : stockData["ChangeinPercent"] as? String ?? "N/A"])
                    dataFields.append(["Day High" : stockData["DaysHigh"] as? String ?? "N/A"])
                    dataFields.append(["Day Low" : stockData["DaysLow"] as? String ?? "N/A"])
                    dataFields.append(["Div/Share" : stockData["DividendShare"] as? String ?? "N/A"])
                    dataFields.append(["Div Yield" : stockData["DividendYield"] as? String ?? "N/A"])
                    dataFields.append(["EBITDA" : stockData["EBITDA"] as? String ?? "N/A"])
                    dataFields.append(["Current Yr EPS Estimate" : stockData["EPSEstimateCurrentYear"] as? String ?? "N/A"])
                    dataFields.append(["Next Qtr EPS Estimate" : stockData["EPSEstimateNextQuarter"] as? String ?? "N/A"])
                    dataFields.append(["Next Yr EPS Estimate" : stockData["EPSEstimateNextYear"] as? String ?? "N/A"])
                    dataFields.append(["Earnings/Share" : stockData["EarningsShare"] as? String ?? "N/A"])
                    dataFields.append(["50D MA" : stockData["FiftydayMovingAverage"] as? String ?? "N/A"])
                    dataFields.append(["Last Trade Date" : stockData["LastTradeDate"] as? String ?? "N/A"])
                    dataFields.append(["Last" : stockData["LastTradePriceOnly"] as? String ?? "N/A"])
                    dataFields.append(["Last Trade Time" : stockData["LastTradeTime"] as? String ?? "N/A"])
                    dataFields.append(["Market Cap" : stockData["MarketCapitalization"] as? String ?? "N/A"])
                    dataFields.append(["Company" : stockData["Name"] as? String ?? "N/A"])
                    dataFields.append(["One Yr Target" : stockData["OneyrTargetPrice"] as? String ?? "N/A"])
                    dataFields.append(["Open" : stockData["Open"] as? String ?? "N/A"])
                    dataFields.append(["PEG Ratio" : stockData["PEGRatio"] as? String ?? "N/A"])
                    dataFields.append(["PE Ratio" : stockData["PERatio"] as? String ?? "N/A"])
                    dataFields.append(["Previous Close" : stockData["PreviousClose"] as? String ?? "N/A"])
                    dataFields.append(["Price-Book" : stockData["PriceBook"] as? String ?? "N/A"])
                    dataFields.append(["Price-Sales" : stockData["PriceSales"] as? String ?? "N/A"])
                    dataFields.append(["Short Ratio" : stockData["ShortRatio"] as? String ?? "N/A"])
                    dataFields.append(["Stock Exchange" : stockData["StockExchange"] as? String ?? "N/A"])
                    dataFields.append(["Symbol" : stockData["Symbol"] as? String ?? "N/A"])
                    dataFields.append(["200D MA" : stockData["TwoHundreddayMovingAverage"] as? String ?? "N/A"])
                    dataFields.append(["Volume" : stockData["Volume"] as? String ?? "N/A"])
                    dataFields.append(["52w High" : stockData["YearHigh"] as? String ?? "N/A"])
                    dataFields.append(["52w Low" : stockData["YearLow"] as? String ?? "N/A"])



                    let stock = Stock(

                        ask: dataFields[0].values.first,
                        averageDailyVolume: dataFields[1].values.first,
                        bid: dataFields[2].values.first,
                        bookValue: dataFields[3].values.first,
                        changeNumeric: dataFields[4].values.first,
                        changePercent: dataFields[5].values.first,
                        dayHigh: dataFields[6].values.first,
                        dayLow: dataFields[7].values.first,
                        dividendShare: dataFields[8].values.first,
                        dividendYield: dataFields[9].values.first,
                        ebitda: dataFields[10].values.first,
                        epsEstimateCurrentYear: dataFields[11].values.first,
                        epsEstimateNextQtr: dataFields[12].values.first,
                        epsEstimateNextYr: dataFields[13].values.first,
                        eps: dataFields[14].values.first,
                        fiftydayMovingAverage: dataFields[15].values.first,
                        lastTradeDate: dataFields[16].values.first,
                        last: dataFields[17].values.first,
                        lastTradeTime: dataFields[18].values.first,
                        marketCap: dataFields[19].values.first,
                        companyName: dataFields[20].values.first,
                        oneYearTarget: dataFields[21].values.first,
                        open: dataFields[22].values.first,
                        pegRatio: dataFields[23].values.first,
                        peRatio: dataFields[24].values.first,
                        previousClose: dataFields[25].values.first,
                        priceBook: dataFields[26].values.first,
                        priceSales: dataFields[27].values.first,
                        shortRatio: dataFields[28].values.first,
                        stockExchange: dataFields[29].values.first,
                        symbol: dataFields[30].values.first,
                        twoHundreddayMovingAverage: dataFields[31].values.first,
                        volume: dataFields[32].values.first,
                        yearHigh: dataFields[33].values.first,
                        yearLow: dataFields[34].values.first,
                        dataFields: dataFields


                    )
                    dispatch_async(dispatch_get_main_queue()) 
                        completion(stock: stock)
                    
                
            
        
    

这是结构:

结构股票

    var 问:字符串?
    var averageDailyVolume:字符串?
    var 出价:字符串?
    var bookValue:字符串?
    var changeNumeric: 字符串?
    var changePercent: 字符串?
    var dayHigh:字符串?
    var dayLow:字符串?
    var 股息共享:字符串?
    var 股息收益率:字符串?
    var ebitda: 字符串?
    var epsEstimateCurrentYear:字符串?
    var epsEstimateNextQtr:字符串?
    var epsEstimateNextYr:字符串?
    var eps: 字符串?
    var 五十天移动平均:字符串?
    var lastTradeDate:字符串?
    var last:字符串?
    var lastTradeTime: 字符串?
    var marketCap:字符串?
    var companyName: 字符串?
    var oneYearTarget:字符串?
    var open: 字符串?
    var pegRatio:字符串?
    var perRatio:字符串?
    var previousClose: 字符串?
    var priceBook:字符串?
    var priceSales:字符串?
    var shortRatio:字符串?
    var stockExchange:字符串?
    var 符号:字符串?
    var twoHundreddayMovingAverage:字符串?
    var 卷:字符串?
    var yearHigh:字符串?
    var yearLow:字符串?

    var 数据字段:[[字符串:字符串]]

我的 swiftStockKit 文件也有不同的 stockurl,这可能会妨碍将数据显示到 UILabel 的能力

let stockURL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22)&env= store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json"

其余的都是一样的。

【问题讨论】:

【参考方案1】:

一些建议:

Yahoo 提供https 所以使用它 您无需在 Alamofire 请求之前致电 dispatch_async。默认情况下,请求将在后台线程上执行。 由于您要映射一长串字段,因此最好使用像 ObjectMapper 这样的 JSON 到对象映射框架。您可以将字段设为本机数据类型,而不是字符串。 我无法解决“线程 1 错误”,因为我没有看到您的 tableView:cellForRowAtIndexPath: 方法。所以这个答案的其余部分是专注于 JSON 处理

您需要稍微重新定义您的 Stock 结构(为简洁起见进行了编辑):

import Foundation
import ObjectMapper

struct Stock: Mappable 
    var symbol: String?
    var ask: Double?
    var lastTradeDate: NSDate?
    // other fields...

    var dataFields = [[String : String]]()

    init?(_ map: Map) 
        // Perform validation of the JSON here
        // Leave blank if you don't need to validate anything
    

    mutating func mapping(map: Map) 
        symbol          <- map["query.results.quote.symbol"] // maps to a String
        ask             <- map["query.results.quote.Ask"]    // maps to a Double

        // You probably want to combine this with LastTradeTime
        // but I'm keeing them as separate for now
        lastTradeDate   <- (map["query.results.quote.LastTradeDate"], MyDateTransform())
    


// We need a custom date formatter since Yahoo doesn't
// return the standard format of yyyy-MM-dd
class MyDateTransform : TransformType 
    typealias Object = NSDate
    typealias JSON = String

    static let dateFormatter =  Void -> NSDateFormatter in
        let formatter = NSDateFormatter()
        formatter.dateFormat = "M/d/yyyy"

        return formatter
    ()

    func transformFromJSON(value: AnyObject?) -> NSDate? 
        if let stringValue = value as? String 
            return MyDateTransform.dateFormatter.dateFromString(stringValue)
         else 
            return nil
        
    

    func transformToJSON(value: NSDate?) -> String? 
        if let dateValue = value 
            return MyDateTransform.dateFormatter.stringFromDate(dateValue)
         else 
            return nil
        
    

用法:

let stockURL = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json"

Alamofire.request(.POST, stockURL)
    .validate()
    .responseJSON  response in
        guard response.result.isSuccess else 
            print(response.result.error!)
            return
        

        // This is all it takes to initiate a new object from JSON
        let stock = Mapper<Stock>().map(response.result.value)
    

【讨论】:

感谢您的回复,我有一个简单的问题。我基本上逐字使用了 Stock 结构代码,但首先添加了 class func fetchPennyStockForBidAndFilter(symbol symbol:String, bid:String, completion:(filteredstock:filteredStock) -> ()) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) ,我想知道我这样做是否正确,其次,我如何将来自 url 的信息放入 uilabel。谢谢。 我不明白您为什么将 dispatch_async 调用到完成处理程序中的后台队列。如果你想设置UILabel 的文本,调用dispatch 到主队列。您想在UILabel 上显示什么信息?例如,要显示要价,您可以设置label.text = "\(filteredStock.ask)"(最好使用NSNumberFormatter 好的,非常感谢,您不必回复,但我打算显示符号和出价。

以上是关于如何使用 AlamoFire 和 Swift 将 JSON 数据放入 UILabel的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Alamofire Swift 4 将图像填充到 UICollectionView

如何将 alamofire 返回 json 解析为 Swift 中的字符串数组?

如何将 json 数据从 alamofire 转换为 swift 对象

如何使用Alamofire Router来组织API调用?(swift Alamofire5)

如何使用 alamofire 将多个 PDF 文件上传到服务器? #Swift 4 #IOS [重复]

如何在 Swift 中使用 Alamofire 将参数作为正文发送到 PUT 方法