Сообщая numberOfRowsInSection, сколько строк ему нужно после синтаксического анализа JSON с JSONDecoder при закрытии с использованием архитектуры MVVM - PullRequest
0 голосов
/ 29 мая 2019

Я использую архитектуру MMVM.

По сути, у меня есть эта функция для анализа JSON в расширении viewModelProtocol в качестве реализации по умолчанию, мои viewModels соответствуют этому протоколу. Большинство viewModels заполняют стандартные представления без каких-либо проблем, за исключением одного, заполняющего tableVIew, но я не могу сказать numberOfRowsInSection, сколько строк ему нужно.

func setWithJSON<T>(completion: @escaping (T) -> Void, error: @escaping (Error) -> Void, service: Services) where T : Decodable {
    let failure: (Error) -> Void = { error in
        self.dataFetchError?(error)
    }

    let completion: (Data) -> Void = { data in

        do {
            let parsedJSON = try JSONDecoder().decode(T.self, from: data)
            completion(parsedJSON)
        } catch {
            self.dataFetchError?(error)
        }
        return
    }

    QueryAPI.shared.setServiceURL(service)
    QueryAPI.shared.fetchData(failure: failure, completion: completion)
}

С его помощью я получаю универсальный тип parsedJSON

Я использую функцию в моем представлении для заполнения моих ячеек в cellForRowAt indexPath: метод, подобный этому.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! ExperienceViewCell

    let error: (Error) -> Void = { error in
        self.handleError(error)
    }

    let completion: ([Experience]) -> Void = { experiences in
        DispatchQueue.main.async { [ weak cell ] in
            cell?.companyLabel.text = experiences[indexPath.row].company
            cell?.positionLabel.text = experiences[indexPath.row].position
            cell?.websiteLabel.text = experiences[indexPath.row].website
            cell?.startDateLabel.text = experiences[indexPath.row].startDate
            cell?.endDateLabel.text = experiences[indexPath.row].endDate
            cell?.summaryTextView.text = experiences[indexPath.row].summary
            cell?.highLightsTextView.text = experiences[indexPath.row].highlights
        }
    }

    viewModel.setWithJSON(completion: completion, error: error, service: .workExperience)
    self.viewModel.dataFetchError = { error in
        self.handleError(error)
    }

    return cell
}

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

Но у меня нет способа сообщить методу numberOfRowsInSection, сколько строк нам нужно, поэтому я жестко запрограммировал его, но это не то, что мне нужно.

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

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

Заранее спасибо.

1 Ответ

1 голос
/ 29 мая 2019

Проблема, которую я вижу, заключается в том, что вы вызываете службу в функции tableView:cellForRowAt:, и это не очень хороший подход.

Попробуйте установить в вашем viewController переменную var experiences: [Experience] = []

В функции viewDidLoad позвоните в службу

func viewDidLoad() {
    super.viewDidLoad()
    let completion: ([Experience]) -> Void = { experiences in
        DispatchQueue.main.async { [ weak self ] in
            self?.experiences = experiences
            self?.tableView.reloadData()
        }
    }
    viewModel.setWithJSON(completion: completion, error: error, service: .workExperience)
    self.viewModel.dataFetchError = { error in
        self.handleError(error)
    }
}

В функции tableView:numberOfRowsInSection: вы можете вернуть experiences.count

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return experiences.count
}

И, наконец, внутри функции tableView:cellForRowAt: вы можете поместить свой код для обновления ячейки:

cell.companyLabel.text = experiences[indexPath.row].company
cell.positionLabel.text = experiences[indexPath.row].position
cell.websiteLabel.text = experiences[indexPath.row].website
cell.startDateLabel.text = experiences[indexPath.row].startDate        
cell.endDateLabel.text = experiences[indexPath.row].endDate
cell.summaryTextView.text = experiences[indexPath.row].summary
cell.highLightsTextView.text = experiences[indexPath.row].highlights

С tableView.reloadData() вы снова вызовете функцию tableView:numberOfRowsInSection: после получения списка своих впечатлений.

...