swift - 最安全的解包选项的方法

标签 swift api optimization error-handling option-type

我完成了我的应用程序编码,现在是时候添加安全功能以防止崩溃了。我还没有实现正确的 nil 处理,测试显示由于未从 API 获取数据而导致一些崩溃。

我的结构有点复杂,我在尝试实现安全性方面迷失了自己,所以我希望你们有新的意见和处理 nil 的最终最安全的方法。我将我的代码后退了几步,供您查看。

代码完整,您可以在 Playground

中尝试

这是结构:

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
}

我对要做什么有一些想法,但我需要能够通过相同的结构获取不同的东西这一事实让我有点困惑。

你怎么看?

最佳答案

你可以尝试这样的事情:

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)
        }
     }

关于swift - 最安全的解包选项的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48408295/

相关文章:

c - 四舍五入到下一个 2 的幂

ios - 如何使用显示 View Controller ?

c# - 编译/优化后如何查看 C# 代码?

json - 使用具有多个 key 的 Decodable 协议(protocol)

api - 准确的 API 响应语言

Android:谷歌地图 Android API:授权失败

rest - 带有正文的 RESTful API 的 HTTP GET 请求

c++ - 任何人都可以降低我的代码的复杂性吗? Codeforces Round113 Div.2 的问题 E

objective-c - 当我解析 json 时,它会将所有内容都变成 nil

ios - 如何理解,调试这部分