Где хранить декодированный массив JSON с сервера и как получить к нему глобальный доступ в viewControllers? - PullRequest
0 голосов
/ 10 июля 2019

В настоящее время я создаю приложение, которое анализирует JSON с моего сервера. С сервера я могу получить массив с моделями JSON. Данные из этого массива должны быть заполнены в виде таблицы. Мой вопрос прост: где хранить декодированный массив с сервера, если я хочу получить к нему доступ из многих viewControllers в моем приложении?

Вот моя модель JSON, пришедшая с сервера.

import Foundation

struct MyModel: Codable {
    var settings: Test?
    var provider: [Provider]
}

extension MyModel {
    struct setting: Codable {
        var name: String
        var time: Int
    }
}


вот как я его декодирую

import Foundation

enum GetResourcesRequest<ResourceType> {
    case success([ResourceType])
    case failure
}

struct ResourceRequest<ResourceType> where ResourceType: Codable {

    var startURL = "https://myurl/api/"
    var resourceURL: URL



    init(resourcePath: String) {
        guard let resourceURL = URL(string: startURL) else {
            fatalError()
        }
        self.resourceURL = resourceURL.appendingPathComponent(resourcePath)
    }


    func fetchData(completion: @escaping
        (GetResourcesRequest<ResourceType>) -> Void ) {
        URLSession.shared.dataTask(with: resourceURL) { data, _ , _ in
            guard let data = data else { completion(.failure)
                return }
            let decoder = JSONDecoder()
            if let jsonData = try? decoder.decode([ResourceType].self, from: data) {
                completion(.success(jsonData))
            } else {
                completion(.failure)
            }
            }.resume()
        }
    }

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Это пример CategoriesProvider.Он просто хранит категории в памяти, и вы можете использовать их в приложении.Это не лучший способ сделать это и не лучшая архитектура, но его легко начать.

class CategoriesProvider {
    static let shared = CategoriesProvider()

    private(set) var categories: [Category]?

    private let categoryRequest = ResourceRequest<Category>(resourcePath: "categories")
    private let dataTask: URLSessionDataTask?

    private init() {}

    func fetchData(completion: @escaping (([Category]?) -> Void)) {
        guard categories == nil else {
            completion(categories)
            return
        }

        dataTask?.cancel()

        dataTask = categoryRequest.fetchData { [weak self] categoryResult in
            var fetchedCategories: [Category]?

            switch categoryResult {
            case .failure:
                print("error")
            case .success(let categories):
                fetchedCategories = categories
            }

            DispatchQueue.main.async {
                self?.categories = fetchedCategories
                completion(fetchedCategories)
            }
        }
    }
}

Я предлагаю использовать URLSessionDataTask для отмены предыдущей задачи.Это может произойти, когда вы звоните fetchData несколько раз один за другим.Вы должны изменить свой ResourceRequest и вернуть значение URLSession.shared.dataTask(...)

Здесь больше подробностей о задаче данных https://www.raywenderlich.com/3244963-urlsession-tutorial-getting-started#toc-anchor-004 (DataTask и DownloadTask)

Теперь вы можете выбирать категории в CategoriesViewController втаким образом:

private func loadTableViewData() {
    CategoriesProvider.shared.fetchData { [weak self] categories in
        guard let self = self, let categories = categories else { return }
        self.categories = categories
        self.tableView.reloadData()
    }
}

В других контроллерах представления вы можете сделать то же самое, но можете проверить категории, прежде чем делать выборку.

if let categories = CategoriesProvider.shared.categories {
    // do something
} else {
    CategoriesProvider.shared.fetchData { [weak self] categories in
        // do something
    }
}
0 голосов
/ 10 июля 2019

Если вы действительно хотите избежать дублирования вызовов load data (), самым простым вариантом будет кэширование данных на диске (CoreData, Realm, File и т. Д.) После первого анализа.

Тогда каждый ViewController, которому нужны данные, может просто запросить вашу систему хранения.

Конечно, недостатком этого подхода является дополнительный код, который вам придется написать для управления связностью вашегоданные, чтобы убедиться, что они правильно управляются в вашем приложении.

...