【问题标题】:Appending Multiple values to arrays in a struct?将多个值附加到结构中的数组?
【发布时间】:2017-09-05 21:12:18
【问题描述】:

我觉得我在尝试这个完全错误的角度......

到目前为止,我已将解析后的 JSON 存储在 10 个不同的数组中:

Alamofire.request(FULL_API).responseJSON { (response) in
        print("AddCoinModel: Full Api = \(FULL_API)")
        if response.result.error == nil {
            guard let data = response.data else { return }
            if let json = JSON(data: data).array {
                for item in json {

                    let id = item["id"].stringValue
                    self.coinImageIdStringArray.append("https://files.coinmarketcap.com/static/img/coins/64x64/\(id).png")

                    let name = item["name"].stringValue
                    self.coinFullNameArray.append(name)

                    let symbol = item["symbol"].stringValue
                    self.coinSymbolArray.append(symbol)

                    let price = item["price_\(self.API_FIAT.lowercased())"].numberValue
                    self.coinPriceArray.append(Double(price))

                    let priceBtc = item["price_btc"].numberValue
                    self.coinPriceInBitcoinArray.append(Double(priceBtc))

                    let volume = item["24h_volume_\(self.API_FIAT.lowercased())"].numberValue
                    self.coinVolume24hArray.append(Double(volume))

                    let marketCap = item["market_cap_\(self.API_FIAT.lowercased())"].numberValue
                    self.coinMarketCapArray.append(Double(marketCap))

                    let percent1h = item["percent_change_1h"].numberValue
                    self.coinPercentChange1hArray.append(Double(percent1h))

                    let percent24h = item["percent_change_24h"].numberValue
                    self.coinPercentChange24hArray.append(Double(percent24h))

                    let percent7d = item["percent_change_7d"].numberValue
                    self.coinPercentChange7dArray.append(Double(percent7d))


                    var coinApiStructArrays = CoinStructure.init(idForImageString: id, fullName: name, symbol: symbol, price: Double(price), priceInBitcoin: Double(priceBtc), volume24h: Double(volume), marketCap: Double(marketCap), pctChange1h: Double(percent1h), pctChange24h: Double(percent24h), pctChange7d: Double(percent7d))
                    print("aaaaa:\(coinApiStructArrays)")
                    self.coinapistruct.append(coinApiStructArrays)
                    print("bbbbb:\(self.coinapistruct)")

                }
                completion(true)
            }
        } else {
            completion(false)
            debugPrint("AddCoinModel: getCoinInfoFunc: \(response.result.error as Any)")
        }
    }  

到目前为止,每当我想将数据传递到 tableview/collectionview 时,我都必须引用每个数组。

我认为必须有一种更简单的方法,所以我尝试为 json 创建一个结构,这样我就可以将所有数据输入到一行代码中,并在将来调用它,而无需键入 10 行代码10 个阵列。

结构:

struct CoinStructure {
    public private(set) var idForImageString: String!
    public private(set) var fullName: String!
    public private(set) var symbol: String!
    public private(set) var price: Double!
    public private(set) var priceInBitcoin: Double!
    public private(set) var volume24h: Double!
    public private(set) var marketCap: Double!
    public private(set) var pctChange1h: Double!
    public private(set) var pctChange24h: Double!
    public private(set) var pctChange7d: Double!
} 

我确实使用了“init”函数:

init(id: String){ idForImageString = id ...} 

然后尝试创建结构体的变量并将json的每个值设置为等于它

 var array = CoinStructure.init(id: id ... etc)

最终当我打印出我得到的 api 的前 5 个结果时:

CoinStructure(idForImageString: bitcoin, fullName: Bitcoin, symbol: BTC, price: 4385.61, priceInBitcoin: 1.0, volume24h: 2766630000.0, marketCap: 72565890651.0, pctChange1h: 0.38, pctChange24h: 3.15, pctChange7d: -4.16)  

(接下来的 4 个基本相同,但值不同..)

好的,到目前为止还可以,但我需要的是以下内容:

CoinStructure(idForImageString: [bitcoin, litecoin], fullName: [Bitcoin, Litecoin], symbol: [BTC, LTC]...)

因此,当我填充 tableview/collectionview 时,我可以调用 indexPath.row 让我们说数组中的第一个索引,然后将“litecoin”、“Litecoin”和“LTC”从数组中拉出。

我觉得我完全错了,必须有一种简单的方法来做到这一点,而不是像我一样把事情弄得一团糟?

非常感谢, 杰里米

【问题讨论】:

  • API_FIAT 是什么?附带说明一下,我建议您使用 DecimalNumber 来表示小数货币值,因为它不会产生 Float/Double 所做的精度错误
  • 我正在使用 coinmarketcap.com api,所以 API_FIAT 只是 api 的货币符号,例如美元、墨西哥比索、印尼盾。我使用了这个,所以当用户更改货币时,我会刷新我的数据并从 api 中提取转换后的货币值。
  • 我明白了。那你应该给它一个更好的名字。也许userFiatCurrencySymbol

标签: arrays swift struct


【解决方案1】:

这种结构的重点是为单个CoinStructure 实例建模单个硬币类型。您正在尝试对多种类型的硬币进行建模,因此您应该创建多个 CoinStructure 实例。

附带说明,无需在名称中添加Structure。我们可以看到它是一个结构。但是,名称的其余部分,即Coin 部分是错误的。这种结构不是对硬币进行建模,而是对加密货币进行建模。

此外,所有成员的可变性,以及它们都是隐式展开的可选项,是一个非常大的危险信号。

这是我将如何建模:

import Foundation

import Foundation

struct CryptoCurrency {
    public let idForImageString: String // FIXME: <--- what is this thing? It's really unclear
    public let fullName: String
    public let symbol: String

    public let price: Decimal
    public let priceInBitcoin: Decimal
    public let volume24h: Decimal
    public let marketCap: Decimal

    public let pctChange1h: Decimal
    public let pctChange24h: Decimal
    public let pctChange7d: Decimal

    init(
        idForImageString: String,
        fullName: String,
        symbol: String,
        price: Decimal,
        priceInBitcoin: Decimal,
        volume24h: Decimal,
        marketCap: Decimal,
        pctChange1h: Decimal,
        pctChange24h: Decimal,
        pctChange7d: Decimal
    ) {
        self.idForImageString = idForImageString
        self.fullName = fullName
        self.symbol = symbol
        self.price = price
        self.priceInBitcoin = priceInBitcoin
        self.volume24h = volume24h
        self.marketCap = marketCap
        self.pctChange1h = pctChange1h
        self.pctChange24h = pctChange24h
        self.pctChange7d = pctChange7d
    }

    init?(fromJSON: JSON) {
        guard let idForImageString = json["id"].stringValue,
            let fullName = json["name"].stringValue,
            let symbol = json["symbol"].stringValue,
            let price = json["price_\(self.API_FIAT.lowercased())"].number?.decimalValue,
            let priceInBitcoin = json["price_btc"].number?.decimalValue,
            let volume24h = json["24h_volume_\(self.API_FIAT.lowercased())"].number?.decimalValue,
            let marketCap = json["market_cap_\(self.API_FIAT.lowercased())"].number?.decimalValue,
            let pctChange1h = json["percent_change_1h"].number?.decimalValue,
            let pctChange24h = json["percent_change_24h"].number?.decimalValue,
            let pctChange7d = json["percent_change_7h"].number?.decimalValue else {
            return nil
        }

        self.init(
            idForImageString: idForImageString,
            fullName: fullName,
            symbol: symbol,
            price: price,
            priceInBitcoin: priceInBitcoin,
            volume24h: volume24h,
            marketCap: marketCap,
            pctChange1h: pctChange1h,
            pctChange24h: pctChange24h,
            pctChange7d: pctChange7d
        )
    }
} 


Alamofire.request(FULL_API).responseJSON { (response) in
    print("AddCoinModel: Full Api = \(FULL_API)")
    guard response.result.error == nil,
        let data = response.data,
        let jsonArray = JSON(data: data).array else {
        completion(false)
        debugPrint("AddCoinModel: getCoinInfoFunc: \(response.result.error as Any)")
        return
    }

    self.cryptocurrencies = jsonArray.map { json in
        guard let cryptocurrency = CryptoCurrency(fromJSON: json) else {
            //FIXME: Handle the error case appropraitely
            fatalError("This JSON doesn't represent a valid CryptoCurrency, and my author didn't handle his errors properly!'")
        }
        return cryptocurrency
    }

    print(self.cryptocurrencies)
    completion(true)
}   

下面是self.cryptocurrencies 的示例:

let cryptocurrencies = [
    CoinStructure(
        idForImageString: bitcoin,  // FIXME: <--- what is this thing? It's really unclear
        fullName: "Bitcoin",
        symbol: "BTC"
        ...
    ),
    CoinStructure(
        idForImageString: litecoin,  // FIXME: <--- what is this thing? It's really unclear
        fullName: "Litecoin",
        symbol: "LTC"
        ...
    ),
]

【讨论】:

  • 嗨,当我尝试使用代码时,我收到一条错误消息,提示“使用未解析的标识符 'json'”。我已经尝试过使用和不使用swiftyjson,仍然是同样的错误。不确定我缺少什么?
  • 另外,'idForImageString' 是字符串版本中每个硬币的图像的 url。后来我使用 alamofire 将其转换为图像。刚刚注意到我在原始评论中犯了一个错误,它不应该说“比特币”,而是图片的网址。
  • @Jeremy 如您所见,我将json 重命名为jsonArray,并将item 重命名为json
  • @Jeremy 那么如果是URL,为什么叫id?为什么是String,而不是URL
  • 啊,我明白了!谢谢 :) 。我在项目一开始就把它变成了一个字符串,从来没有真正考虑过。我把它称为 id,因为我从 api 得到了硬币 id(例如“比特币”或“莱特币”),然后插值进入以 .../bitcoin.png 结尾的图像的 URL。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
相关资源
最近更新 更多