Swift 3:解开来自数组的可选值的最安全的方法是什么?

时间:2016-12-02 19:14:00

标签: ios swift swift3

首先,我初始化变量以保存股票数据

var applePrice: String?
var googlePrice: String?
var twitterPrice: String?
var teslaPrice: String?
var samsungPrice: String?
var stockPrices = [String]()

我从YQL获取当前股票价格,并将这些值放入数组

func stockFetcher() {

    Alamofire.request(stockUrl).responseJSON { (responseData) -> Void in
        if((responseData.result.value) != nil) {
            let json = JSON(responseData.result.value!)
            if let applePrice = json["query"]["results"]["quote"][0]["Ask"].string {
                print(applePrice)
                self.applePrice = applePrice
                self.tableView.reloadData()
            }
            if let googlePrice = json["query"]["results"]["quote"][1]["Ask"].string {
                print(googlePrice)
                self.googlePrice = googlePrice
                self.tableView.reloadData()
            }
            if let twitterPrice = json["query"]["results"]["quote"][2]["Ask"].string {
                print(twitterPrice)
                self.twitterPrice = twitterPrice
                self.tableView.reloadData()
            }
            if let teslaPrice = json["query"]["results"]["quote"][3]["Ask"].string {
                print(teslaPrice)
                self.teslaPrice = teslaPrice
                self.tableView.reloadData()
            }
            if let samsungPrice = json["query"]["results"]["quote"][4]["Ask"].string {
                print(samsungPrice)
                self.samsungPrice = samsungPrice
                self.tableView.reloadData()
            }
            let stockPrices = ["\(self.applePrice)", "\(self.googlePrice)", "\(self.twitterPrice)", "\(self.teslaPrice)", "\(self.samsungPrice)"]
            self.stockPrices = stockPrices
            print(json)
        }
    }
}

在cellForRowAt indexPath函数中我打印到标签

    if self.stockPrices.count > indexPath.row + 1 {
        cell.detailTextLabel?.text = "Current Stock Price: \(self.stockPrices[indexPath.row])" ?? "Fetching stock prices..."
    } else {
        cell.detailTextLabel?.text = "No data found"
    }

我遇到了打印当前股票价格的问题:可选("股票价格"),带有可选字样。我认为这是因为我给它提供了一系列可选值,但我有点必须知道,因为我实际上不知道是否有来自YQL的数据,5个股票中的一个可能是nil而其他人有数据。通过阅读其他类似的问题,我可以看到解决方案是用!打开值,但是我不太确定如何实现该解决方案,因为它是一个包含可能数据的数组是nil,而不仅仅是Int或其他东西。

如何安全地解开这里并摆脱“可选”一词?

3 个答案:

答案 0 :(得分:3)

首先关闭:

每当你多次重复相同的代码块并且只将值从0增加到某个最大值时,它就是代码味道。您应该考虑采用不同的方式来处理它。

您应该使用数组来执行此处理。

索引的一组枚举如何:

enum companyIndexes: Int {
  case apple
  case google
  case twitter
  case tesla
  //etc...
}

现在,您可以使用循环遍历数组并更清晰地安装值:

var stockPrices = [String?]()
Alamofire.request(stockUrl).responseJSON { (responseData) -> Void in
    if((responseData.result.value) != nil) {
        let json = JSON(responseData.result.value!)
        let pricesArray = json["query"]["results"]["quote"]
        for aPriceEntry in pricesArray {
           let priceString = aPriceEntry["ask"].string
           stockPrices.append(priceString)
        }
   }
}

从阵列中获取价格:

let applePrice = stockPrices[companyIndexes.apple.rawValue]

这将导致可选。

您可以使用nil合并运算符(??)将nil值替换为"没有可用价格的字符串。":

let applePrice = stockPrices[companyIndexes.apple.rawValue] ?? "No price available"

或如其他答案所示:

if let applePrice = stockPrices[companyIndexes.apple.rawValue] {
   //we got a valid price
} else
   //We don't have a price for that entry
}

答案 1 :(得分:0)

我在Xcode之外写这个(所以可能存在拼写错误),但这种逻辑应该有效。

if self.stockPrices.count > indexPath.row + 1 {
    var txt = "Fetching stock prices..."
    if let price = self.stockPrices[indexPath.row] {
        txt = price
    }
    cell.detailTextLabel?.text = txt
} else {
    cell.detailTextLabel?.text = "No data found"
}

答案 2 :(得分:0)

为安全展开使用该代码:

if let currentStockPrice = self.stockPrices[indexPath.row]
{
    // currentStockPrice available there
}
// currentStockPrice unavailable

如果您需要将多个变量一个接一个地展开,可能会导致代码无法读取。在这种情况下使用此模式

guard let currentStockPrice = self.stockPrices[indexPath.row]
else
{
    // currentStockPrice is unavailable there
    // must escape via return, continue, break etc.
}
// currentStockPrice is available