SWIFT - Как исправить обратный вызов, произошедший слишком поздно - PullRequest
0 голосов
/ 14 февраля 2019

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

Код от сетевого менеджера

  func getArticles(completion: @escaping PListCompletion) {

        guard let url = plistUrlString else { return }
        let urlRequest = URLRequest(url: url)
        let defaultConfig = URLSessionConfiguration.default
        let session = URLSession(configuration: defaultConfig)
        let task = session.dataTask(with: urlRequest) { (data, response, error) in
            do {
                if let data = data {
                    let articles = try PropertyListDecoder().decode([Articles].self, from: data)
                    self.callBackOnMainThread(completion: completion, response: .success(response: PlistResponseData(results: articles)))
                }
            } catch {
                print(error)
                completion(.failure(error: error))
            }
        }
        task.resume()
    }

    private func callBackOnMainThread(completion: @escaping PListCompletion, response: PlistResponse) {
        DispatchQueue.main.async {
            completion(response)
        }
    }
final class ArticleListProvider {

     var articles: [Articles]

    convenience init() {
        self.init(articles: [])

        self.provideArticles { (article) in
            self.articles.append(contentsOf: article)
        }
    }

    init(articles: [Articles]) {
        self.articles = articles
    }

    func articleCount() -> Int {
//used for tableVC cells but returning 0
        return self.articles.count
    }

    func articleAtIndex(_ index: Int) -> Articles? {
        return articles[index]
    }

    func provideArticles(completion: @escaping ([Articles]) -> Void) {
        ArticleDetailsNetworkManager.sharedInstance.getArticles { [weak self] (response) in
            guard let weakSelf = self else { return}
            switch response {
            case .success(let plistData):
                weakSelf.articles = plistData.results
            case .failure(let error):
                print(error.localizedDescription)
            }
            completion(weakSelf.articles)
        }
    }
}

tableVC

final class ArticleListController: UITableViewController {
    fileprivate let CellIdentifier = "Cell"

    fileprivate let articleListProvider: ArticleListProvider

    override init(style: UITableViewStyle) {
        self.articleListProvider = ArticleListProvider()
        super.init(style:style)
    }

    required init?(coder: NSCoder) {
        self.articleListProvider = ArticleListProvider()
        super.init(coder: coder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableViewCell()
        tableView.reloadData()
    }
}

extension ArticleListController {

    func setupTableViewCell() {
        tableView.register(ArticleTableViewCell.self, forCellReuseIdentifier: CellIdentifier)
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

//this is returning 0 when it should be returning the amount of articles from the articleProvider, where the networking call is being made 

        return articleListProvider.articleCount()
    }

Не знаю, имеет ли это значение, но этоработал на Xcode 9.4, (хотя без обратного вызова), эта проблема возникла после обновления до 10.1

1 Ответ

0 голосов
/ 14 февраля 2019

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

Измените метод инициализации следующим образом:

convenience init(callback: @escaping () -> Void) {
    self.init(articles: [])

    self.provideArticles { (article) in
        self.articles.append(contentsOf: article)
        callback()
    }
}

И используйте его из контроллера представления следующим образом.:

self.articleListProvider = ArticleListProvider{ [weak self]
    guard let weakSelf = self else { return}
    weakSelf.yourTableView.reloadData()
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...