НАЧАЛЬНАЯ ЦЕЛЬ :
Иметь представление со списком ячеек, расположенных вертикально, с отображением некоторой информации. Как только пользователь нажимает на ячейку, чтобы показать новое представление с дополнительной информацией.
ДОРОГА ТАК (карри на своенравном сыне!):
- Я создал 2 контроллера представления: ViewController (создание подклассов UICollectionViewController, UICollectionViewDelegateFlowLayout) и DetailViewController (создание подклассов UIViewController).
- Я создал Ячейку , которую ViewController использует для генерации представления коллекции, и DetailView , которую DetailViewController использует
- Я создал структуру с именем Detail в качестве пользовательского типа данных, который обеспечивает хранение данных с использованием свойств (например, имя, фамилия, адрес и т. Д.)
Структура:
struct Detail: Decodable {
let name: String?
let surname: String?
let address: String?
let description: String?
}
Я использую следующие данные для тестирования (после завершения тестирования я получу эти данные из вызова API). Я поместил его внутри ViewController :
let details: [Detail] = [Detail(name: "Chris", surname: "Doe", address: "Neverland 31", description: "This is a description about Chris Doe"), Detail(name: "Tony", surname: "Cross", address: "Galaxy Road 1", description: "This is a description about Tony Cross")]
Для создания ячеек используйте информацию выше и метод:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
А также:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! Cell
Поскольку метод требует, чтобы мы возвращали UICollectionViewCell, я сначала отправляю связанную информацию в Cell, выполняя следующие действия:
cell.details = details[indexPath.item]
return cell
Внутри ячейки Я создал следующее свойство, используя didSet , чтобы помочь мне получить информацию:
var details: Detail? {
didSet {
guard let details = details else { return }
guard let name = details.name else { return }
....
....
}
Как вы понимаете, используя информацию, поступающую из ViewController, я динамически создавал каждую ячейку.
В этот момент все было хорошо.
Затем я попытался показать подробный вид при нажатии на ячейку. Для этого я следовал той же практике внутри метода:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let detailView = DetailView()
detailView.details = details[indexPath.item]
let detailViewController = DetailViewController()
detailViewController.modalTransitionStyle = .coverVertical
self.present(detailViewController, animated: true, completion: nil)
}
Опять же, в DetailView Я использую тот же подход, чтобы получить данные, связанные с выбранным элементом. Таким образом, я могу получить доступ к данным ячейки, выбранной пользователем, как показано ниже:
import UIKit
class DetailView: UIView {
var dismissDetailViewAction: (() -> Void)?
var details: Detail? {
didSet {
// get details
guard let details = details else { return }
guard let name = details.name else { return }
guard let surname = details.surname else { return }
guard let address = details.address else { return }
guard let description = details.description else { return }
// print description and it shows in the console but not in the view
print(description)
let attributedTextDescription = NSMutableAttributedString(string: description, attributes: [NSAttributedStringKey.font: UIFont.FontBook.AvertaRegular.of(size: 20), NSAttributedStringKey.foregroundColor: UIColor.white])
briefDescription.attributedText = attributedTextDescription
briefDescription.textAlignment = .center
briefDescription.textColor = .white
briefDescription.numberOfLines = 0
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not yet been implemented")
}
fileprivate func setupView() {
setupDescriptionText()
setupCloseButton()
}
let briefDescription: UITextView = {
let text = UITextView()
text.textColor = .red
return text
}()
let closeButton: UIButton = {
let button = UIButton(title: "Close", font: UIFont.FontBook.AvertaRegular.of(size: 18), textColor: .white, cornerRadius: 5)
button.backgroundColor = .black
button.addTarget(self, action: #selector(closeDetailView), for: .touchUpInside)
return button
}()
fileprivate func setupDescriptionText() {
self.addSubview(briefDescription)
briefDescription.translatesAutoresizingMaskIntoConstraints = false
briefDescription.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
briefDescription.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -5).isActive = true
briefDescription.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
briefDescription.heightAnchor.constraint(equalToConstant: 300).isActive = true
}
fileprivate func setupCloseButton() {
self.addSubview(closeButton)
closeButton.translatesAutoresizingMaskIntoConstraints = false
closeButton.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
closeButton.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
closeButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 40).isActive = true
closeButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -40).isActive = true
closeButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
}
@objc func closeDetailView() {
dismissDetailViewAction?()
}
}
Итак, что я на самом деле делаю, так это разрабатываю статическую часть представления вне didSet, и что такое динамическая часть внутри didSet. Это работает с ячейками collectionView.
Я использую DetailViewController , чтобы отобразить DetailView и отключить себя, когда пользователь нажимает кнопку «Закрыть».
import UIKit
class DetailViewController: UIViewController {
// reference DetailView view
var detailView: DetailView!
override func viewDidLoad() {
super.viewDidLoad()
// setup view elements
setupView()
}
fileprivate func setupView() {
let mainView = DetailView(frame: self.view.frame)
self.detailView = mainView
self.view.addSubview(detailView)
self.homeDetailView.dismissDetailViewAction = dismissDetailView
// pin view
self.detailView.translatesAutoresizingMaskIntoConstraints = false
self.detailView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
self.detailView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
self.detailView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.detailView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
}
fileprivate func dismissDetailView() {
// dismiss current (DetailViewController) controller
self.dismiss(animated: true, completion: nil)
}
}
Причина, по которой я это сделал, заключается в том, что мне нравится поддерживать свои ViewControllers как можно более чистыми (Massive View Controller, а не мое).
ПРОБЛЕМА
Все построено без проблем, но когда я щелкаю ячейку, чтобы перейти к DetailView, информация не отображается.
странная часть
Внутри DetailView -> didSet, когда я использую print (name), он работает просто отлично (вы видите правильное имя в консоли). Но когда я пытаюсь использовать это значение внутри представления, оно не будет отображаться.
И я знаю, что мой DetailView в порядке, так как, если я использую в нем жестко закодированные значения, он работает (вы видите правильный результат).
Любой совет, почему это не работает должным образом?
PS: Я строю все это программно. Раскадровки не задействованы.
Заранее спасибо и извините за потерянный пост.