// // MainViewController.swift // LiveLikeGiphyChallenge // // import UIKit class MainViewController: UIViewController { static private let cellSpacing: CGFloat = 10.0 private let viewModel = GiphyViewModel() fileprivate let stackView: UIStackView = { let stackView = UIStackView() stackView.distribution = .fill stackView.axis = .vertical stackView.spacing = cellSpacing stackView.translatesAutoresizingMaskIntoConstraints = false return stackView }() fileprivate let searchBar: UISearchBar = { let searchBar = UISearchBar(frame: .zero) searchBar.searchTextField.placeholder = "Search the gifs you love from Giphy" searchBar.returnKeyType = .search searchBar.translatesAutoresizingMaskIntoConstraints = false searchBar.heightAnchor.constraint(equalToConstant: 50).isActive = true return searchBar }() fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.minimumLineSpacing = cellSpacing layout.minimumInteritemSpacing = cellSpacing let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.register(GiphyCollectionViewCell.self, forCellWithReuseIdentifier: "GiphyCollectionViewCell") collectionView.register(ActivityIndicatorCollectionViewCell.self, forCellWithReuseIdentifier: "ActivityIndicatorCollectionViewCell") collectionView.translatesAutoresizingMaskIntoConstraints = false return collectionView }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white setupStackView() setupSearchBar() setupCollectionView() setupViewModel() } func setupStackView() { view.addSubview(stackView) stackView.addArrangedSubview(searchBar) stackView.addArrangedSubview(collectionView) NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20), stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 10), stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10), stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10) ]) } func setupCollectionView() { collectionView.delegate = self collectionView.dataSource = self } func setupSearchBar() { searchBar.delegate = self } func setupViewModel() { viewModel.didFinishLoadingData = { [weak self] success in self?.collectionView.reloadData() } viewModel.fetchGiphyImages() } } extension MainViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return viewModel.items.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if !viewModel.isLoadingList { if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GiphyCollectionViewCell", for: indexPath) as? GiphyCollectionViewCell { let url = viewModel.items[indexPath.row] cell.setupCell(url: url) return cell } } else { if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ActivityIndicatorCollectionViewCell", for: indexPath) as? ActivityIndicatorCollectionViewCell { cell.spinner.startAnimating() return cell } } return UICollectionViewCell() } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let itemsPerRow: CGFloat = UIDevice.current.orientation.isLandscape ? 4 : 2 let cellSize = collectionView.frame.width / itemsPerRow - MainViewController.cellSpacing return CGSize(width: cellSize, height: cellSize) } func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { viewModel.tryToLoadMore(row: indexPath.row) } } extension MainViewController: UISearchBarDelegate { func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { scrollToTop() DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.viewModel.searchTerm = searchText } } func scrollToTop() { if !viewModel.items.isEmpty { collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .top, animated: true) } } }