重用API管理器类和存储数据以便可重用的最佳方法是什么

时间:2018-09-29 19:18:25

标签: ios swift xcode class

我有一个PageViewController,它创建DataViewController的实例,并且此dataViewController需要执行一些(从管理器类)调用的API,然后使用该数据填充其UI。即添加页面后,dataViewController会获取其数据源,并使用该数据源来告诉API获取什么。

问题是,因为我可以添加多个页面,并且我需要例如数据来为每个页面形成图形,所以每次视图控制器加载时都必须进行API调用,我感到这很不方便,而且必须是一种更好的方式,可以在会话的整个生命周期内存储数据。由于dataViewController的每个实例都使用相同的API管理器,因此我刷新它们以清除它们拥有的所有数据,然后再次针对加载的页面启动API调用,这有时可能会混淆数据,从而显示两个页面中的信息混合或显示错误页面上的错误数据。这是我的一个API管理器的示例,该示例使用dataViewController的dataObject获取图表数据:

import Foundation

struct Root: Codable {
let prices: [Price]
}
struct Price: Codable {
let date: Date
let price: Double
}

class CGCharts {

var priceData = [Price]()
var graphPrices: [Double] = []
var graphTimes: [String] = []

static let shared = CGCharts()

var defaultCurrency = UserDefaults.standard.string(forKey: "DefaultCurrency")!

var coin = ""
var currency = ""
var days = ""

    enum GraphStatus {
    case day, week, month
}

    var graphSetup = GraphStatus.day

    func getData(arr: Bool, completion: @escaping (Bool) -> ()) {

    switch graphSetup {

    case .day:
        days = "1"
    case .week:
        days = "14"
    case .month:
        days = "30"

    }

    let urlJSON = "https://api.coingecko.com/api/v3/coins/\(coin)/market_chart?vs_currency=\(defaultCurrency)&days=\(days)"

    guard let url = URL(string: urlJSON) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data = data else { return }

        do {
            let prices = try JSONDecoder().decode(Root.self, from: data).prices
            print(prices.first!.date.description(with:.current))  // "Saturday, September 1, 2018 at 6:25:38 PM Brasilia Standard Time\n"
            print(prices[0].price)
            self.priceData = prices

            for element in prices {
                self.graphPrices.append(element.price)
            }
            for element in prices {
                self.graphTimes.append(element.date.description(with: nil))

            }

            completion(arr)

        } catch {
            print(error)
        }

        }.resume()

}

func refresh(arr: Bool, completion: @escaping (Bool) -> ()) {

    defaultCurrency = UserDefaults.standard.string(forKey: "DefaultCurrency")!
    graphPrices = []
    graphTimes = []


    completion(arr)
}

}

在这里您可以看到我正在获取数据,使用可编码解析,在这种情况下,我发现分离数据的最佳方法是使用两个数组,我基本上希望将2个数组存储在内存中该特定dataObject的数据,以便在页面视图中加载具有相同dataObject的页面时,它将首先检查该数据是否已经存在,并使用该数据,而不是每次都需要获取新信息,而我必须清除该类。希望我有道理,谢谢。

1 个答案:

答案 0 :(得分:0)

在对NSCache进行了更多研究之后,我了解到您可以将数据保存到磁盘或缓存中并轻松地再次访问它们。我发现了Saoud M. Rizwan here

制作的这种出色的存储类

这使得存储结构超级容易:

var messages = [Message]()

for i in 1...4 {
let newMessage = Message(title: "Message \(i)", body: "...")
messages.append(newMessage)
}

Storage.store(messages, to: .documents, as: "messages.json")

并检索它们:

let messagesFromDisk = Storage.retrieve("messages.json", from: .documents, as: [Message].self)

完美存储来自API的数据,这样您就不必进行太多的API调用,如果您的请求受到限制,这尤其有用。就我而言,我使用该方法检查存储是否存在,是否使用该方法加载数据,如果不存在,则执行api调用,使用此类存储数据,然后再次运行检查以看到数据在那里并使用它,它可能不是最有效的,但它可以工作。

我的例子:

var prices: [Double] = []
var days: [String] = []
var priceData = [Price]()

var graphDataExists = false
func checkGraphStorage() {
    if Storage.fileExists("\(dataObject)GraphPrices", in: 
Storage.Directory.caches) {
        print("UsingSavedData")
        self.priceData = Storage.retrieve("\(dataObject)GraphPrices", from: 
Storage.Directory.caches, as: [Price].self)

        if self.prices.isEmpty {
        for element in self.priceData {
            self.prices.append(element.price)
        }
        for element in self.priceData {
            self.days.append(element.date.description(with: nil))
            graphDataExists = true

        }
        } else {

        }
        DispatchQueue.main.async {
             self.chartView.animate(xAxisDuration: 4.0)
            self.lineChartUpdate(dataPoints: self.days, values: self.prices)
        }


    } else {
        self.prepareGraph(arr: true) { (success) in

        }

    }
}