我完成了我的应用程序编码,现在是时候添加安全功能以防止崩溃。我没有实现正确的nil
处理,测试显示从API中获取数据时发生了一些崩溃。
我的结构有点复杂,我迷失了自己试图实现安全性的事情,所以我希望你们有新的见解和最终最安全的方式来处理nil
。我把我的代码退了几步,供你查看。
代码完成,您可以在Playground
以下是struct
:
struct Ripple : Decodable {
private enum CodingKeys : String, CodingKey { case raw = "RAW" }
let raw : RippleRAW
}
struct RippleRAW : Decodable {
private enum CodingKeys : String, CodingKey { case xrp = "XRP" }
let xrp : RippleCURRENCIES
}
struct RippleCURRENCIES : Decodable {
private enum CodingKeys : String, CodingKey {
case usd = "USD"
case rub = "RUB"
}
let usd : RippleUSD?
let rub : RippleRUB?
}
struct RippleUSD : Decodable {
let price : Double
let percentChange24h : Double
private enum CodingKeys : String, CodingKey {
case price = "PRICE"
case percentChange24h = "CHANGEPCT24HOUR"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
percentChange24h = try container.decode(Double.self, forKey: .percentChange24h)
do {
price = try container.decode(Double.self, forKey: .price)
} catch DecodingError.typeMismatch(_, _) {
let stringValue = try container.decode(String.self, forKey: .price)
price = Double(stringValue)!
}
}
}
struct RippleRUB : Decodable {
let price : Double
let percentChange24h : Double
private enum CodingKeys : String, CodingKey {
case price = "PRICE"
case percentChange24h = "CHANGEPCT24HOUR"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
percentChange24h = try container.decode(Double.self, forKey: .percentChange24h)
do {
price = try container.decode(Double.self, forKey: .price)
} catch DecodingError.typeMismatch(_, _) {
let stringValue = try container.decode(String.self, forKey: .price)
price = Double(stringValue)!
}
}
}
这里我从API获取和解码数据:
enum MyErrorXRP : Error {
case FoundNil(String)
}
class RippleInfo : NSObject {
func fetchRippleInfo(forCurrency currency: String, _ completion: @escaping (Ripple?, Error?) -> Void) {
let url = URL(string: "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=XRP&tsyms=\(currency)")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
if let rippleData = try? JSONDecoder().decode(Ripple.self, from: data) {
completion(rippleData, nil)
} else {
throw MyErrorXRP.FoundNil("rippleData")
}
} catch {
print(error)
}
}
task.resume()
}
}
这些是调用函数,在应用程序中用于更新标签:
func rippleDataUpdate() {
if MainViewController.currencyRUB == true {
RippleInfo().fetchRippleInfo(forCurrency: "RUB", { (ripple, error) in
if ripple != nil {
print("ok ripple rub")
} else {
print("notworking")
}
self.updateRippleUI(with: ripple!)
})
}
}
func updateRippleUI(with rippleInfo: Ripple) {
MainViewController.rippleDoublePrice = Double((rippleInfo.raw.xrp.rub?.price)!)
MainViewController.xrpPercent = Double((rippleInfo.raw.xrp.rub?.percentChange24h)!)
}
所有这些代码都包含在MainViewController
中,以便在Playground
中使用以下变量运行:
class MainViewController : UIViewController {
static var rippleDoublePrice : Double = 0
static var xrpPercent : Double = 0
static var currencyRUB : Bool = true
}
我有一些关于该做什么的想法,但事实上我需要能够通过相同的结构获取不同的东西让我感到困惑。
您有什么看法?
答案 0 :(得分:0)
您可以尝试这样的事情:
func rippleDataUpdate() {
if MainViewController.currencyRUB == true {
RippleInfo().fetchRippleInfo(forCurrency: "RUB", { (ripple, error) in
guard ripple != nil else {
return
}
self.updateRippleUI(with: ripple!)
})
}
}
func updateRippleUI(with rippleInfo: Ripple) {
if let price = rippleInfo.raw.xrp.rub?.price {
MainViewController.rippleDoublePrice = Double(price)
}
if let percent = rippleInfo.raw.xrp.rub?.percentChange24h {
MainViewController.xrpPercent = Double(percent)
}
}