MainViewController.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // MainViewController.swift
  3. // LiveLikeGiphyChallenge
  4. //
  5. //
  6. import UIKit
  7. class MainViewController: UIViewController {
  8. static private let cellSpacing: CGFloat = 10.0
  9. private let viewModel = GiphyViewModel()
  10. fileprivate let stackView: UIStackView = {
  11. let stackView = UIStackView()
  12. stackView.distribution = .fill
  13. stackView.axis = .vertical
  14. stackView.spacing = cellSpacing
  15. stackView.translatesAutoresizingMaskIntoConstraints = false
  16. return stackView
  17. }()
  18. fileprivate let searchBar: UISearchBar = {
  19. let searchBar = UISearchBar(frame: .zero)
  20. searchBar.searchTextField.placeholder = "Search the gifs you love from Giphy"
  21. searchBar.returnKeyType = .search
  22. searchBar.translatesAutoresizingMaskIntoConstraints = false
  23. searchBar.heightAnchor.constraint(equalToConstant: 50).isActive = true
  24. return searchBar
  25. }()
  26. fileprivate let collectionView: UICollectionView = {
  27. let layout = UICollectionViewFlowLayout()
  28. layout.minimumLineSpacing = cellSpacing
  29. layout.minimumInteritemSpacing = cellSpacing
  30. let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  31. collectionView.register(GiphyCollectionViewCell.self, forCellWithReuseIdentifier: "GiphyCollectionViewCell")
  32. collectionView.register(ActivityIndicatorCollectionViewCell.self, forCellWithReuseIdentifier: "ActivityIndicatorCollectionViewCell")
  33. collectionView.translatesAutoresizingMaskIntoConstraints = false
  34. return collectionView
  35. }()
  36. override func viewDidLoad() {
  37. super.viewDidLoad()
  38. view.backgroundColor = .white
  39. setupStackView()
  40. setupSearchBar()
  41. setupCollectionView()
  42. setupViewModel()
  43. }
  44. func setupStackView() {
  45. view.addSubview(stackView)
  46. stackView.addArrangedSubview(searchBar)
  47. stackView.addArrangedSubview(collectionView)
  48. NSLayoutConstraint.activate([
  49. stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
  50. stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 10),
  51. stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
  52. stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10)
  53. ])
  54. }
  55. func setupCollectionView() {
  56. collectionView.delegate = self
  57. collectionView.dataSource = self
  58. }
  59. func setupSearchBar() {
  60. searchBar.delegate = self
  61. }
  62. func setupViewModel() {
  63. viewModel.didFinishLoadingData = { [weak self] success in
  64. self?.collectionView.reloadData()
  65. }
  66. viewModel.fetchGiphyImages()
  67. }
  68. }
  69. extension MainViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  70. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  71. return viewModel.items.count
  72. }
  73. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  74. if !viewModel.isLoadingList {
  75. if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GiphyCollectionViewCell", for: indexPath) as? GiphyCollectionViewCell {
  76. let url = viewModel.items[indexPath.row]
  77. cell.setupCell(url: url)
  78. return cell
  79. }
  80. } else {
  81. if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ActivityIndicatorCollectionViewCell", for: indexPath) as? ActivityIndicatorCollectionViewCell {
  82. cell.spinner.startAnimating()
  83. return cell
  84. }
  85. }
  86. return UICollectionViewCell()
  87. }
  88. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  89. let itemsPerRow: CGFloat = UIDevice.current.orientation.isLandscape ? 4 : 2
  90. let cellSize = collectionView.frame.width / itemsPerRow - MainViewController.cellSpacing
  91. return CGSize(width: cellSize, height: cellSize)
  92. }
  93. func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  94. viewModel.tryToLoadMore(row: indexPath.row)
  95. }
  96. }
  97. extension MainViewController: UISearchBarDelegate {
  98. func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
  99. scrollToTop()
  100. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  101. self.viewModel.searchTerm = searchText
  102. }
  103. }
  104. func scrollToTop() {
  105. if !viewModel.items.isEmpty {
  106. collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .top, animated: true)
  107. }
  108. }
  109. }