
ToDo List

TableViewController.swift
import UIKit
extension TodoTableViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        guard let txt = searchController.searchBar.text?.lowercased() else { return }
        
        self.filteredList.specialList = self.list.specialList.filter{ $0.main.lowercased().contains(txt) }
        self.filteredList.todoList = self.list.todoList.filter{
            $0.main.lowercased().contains(txt) }
            
        self.tableView.reloadData()
    }  
}
class TodoTableViewController: UITableViewController {
    
    var list = ToDoInformation()            
    var filteredList = ToDoInformation()    
    
    
    var isFiltering: Bool {
        let searchController = self.navigationItem.searchController
        let isActive = searchController?.isActive ?? false
        let isSearchBarHasText = searchController?.searchBar.text?.isEmpty == false
        
        print(isActive && isSearchBarHasText)
        
        return isActive && isSearchBarHasText
    }
    
    
    func setupSearchController() {
        let searchController = UISearchController(searchResultsController: nil)
        self.navigationItem.searchController = searchController
        
        searchController.searchResultsUpdater = self
    }
    
    func setupTableView() {
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }
    
    
    @IBOutlet var pullDownButton: UIButton!
    @IBOutlet var newTextField: UITextField!
    @IBOutlet var okButton: UIButton!
    
    
    var option = Option.일반.rawValue
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let nib = UINib(nibName: identifier.TodoTableViewCell.rawValue, bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: identifier.TodoTableViewCell.rawValue)
        
        
        designPullDownButton(pullDownButton)
        
        
        setupTableView()
        setupSearchController()
    }
    
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }
    
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return (section == 0) ? "즐겨찾기" : "일반"
    }
    
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        if (section == 0) {
            if (isFiltering) {
                return filteredList.specialList.count
            } else {
                return list.specialList.count
            }
        }
        else {
            if (isFiltering) {
                return filteredList.todoList.count
            } else {
                return list.todoList.count
            }
        }
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: identifier.TodoTableViewCell.rawValue) as! TodoTableViewCell
        
        
        if (indexPath.section == 0 ) {
            if (isFiltering) {
                let row = filteredList.specialList[indexPath.row]  
                cell.designCell(row)
            }
            else {
                let row = list.specialList[indexPath.row]  
                cell.designCell(row)
            }
        }
        else if (indexPath.section == 1  ){
            if (isFiltering) {
                let row = filteredList.todoList[indexPath.row]
                cell.designCell(row)
            }
            else {
                let row = list.todoList[indexPath.row]
                cell.designCell(row)
            }
        }
        
        
        
        cell.doneCallBackMethod = { [weak self] in
            
            
            if (indexPath.section == 0 && !((self?.list.specialList[indexPath.row].done)!)  ) {
                var tmp: ToDo = (self?.list.specialList[indexPath.row])!
                self?.list.specialList.remove(at: indexPath.row)
                
                tmp.done = true;
                
                self?.list.specialList.insert(tmp, at: (self?.list.specialList.count)!)
            }
            else if (indexPath.section == 1 && !((self?.list.todoList[indexPath.row].done)!)  ) {
                var tmp: ToDo = (self?.list.todoList[indexPath.row])!
                self?.list.todoList.remove(at: indexPath.row)
                
                tmp.done = true;
                
                self?.list.todoList.insert(tmp, at: (self?.list.todoList.count)!)
            }
            
            tableView.reloadData()
        }
        
        
        
        cell.specialCallBackMethod = { [weak self] in
            if (indexPath.section == 0 && !((self?.list.specialList[indexPath.row].done)!)) {   
                
                var tmp: ToDo = (self?.list.specialList[indexPath.row])!
                self?.list.specialList.remove(at: indexPath.row)
                
                tmp.special = false;
                
                self?.list.todoList.insert(tmp, at: 0)
            }
            else if (indexPath.section == 1 && !((self?.list.todoList[indexPath.row].done)!)) {  
                var tmp: ToDo = (self?.list.todoList[indexPath.row])!
                self?.list.todoList.remove(at: indexPath.row)
                tmp.special = true
                
                self?.list.specialList.insert(tmp, at: 0)
            }
            
            tableView.reloadData()
        }
        
        
        
        return cell
    }
   
    
    func designPullDownButton(_ sender: UIButton) {
        
        sender.setTitle(option, for: .normal)
        
        let op1 = UIAction(title: Option.즐겨찾기.rawValue) { _ in
            self.option = Option.즐겨찾기.rawValue
            sender.setTitle(self.option, for: .normal)
        }
        
        let op2 = UIAction(title: Option.일반.rawValue) { _ in
            self.option = Option.일반.rawValue
            sender.setTitle(self.option, for: .normal)
        }
        
        let buttonMenu = UIMenu(title: "선택", children: [op1, op2])
        
        sender.menu = buttonMenu
    }
    
    
    func checkTextField(_ sender: UITextField) -> Bool {
        if let txt = sender.text {
            if txt.count >= 1 {
                return true
            }
        }
        
        return false
    }
    
    
    func updateList() {
        if (checkTextField(newTextField)) {
            let txt = newTextField.text!
            
            if option == Option.일반.rawValue {
                list.todoList.insert(ToDo(done: false, main: txt, special: false), at: 0)
                
                tableView.reloadData()
                
                newTextField.text = ""
            }
            else if option == Option.즐겨찾기.rawValue {
                list.specialList.insert(ToDo(done: false, main: txt, special: true), at: 0)
                
                tableView.reloadData()
                
                newTextField.text = ""
                
            }
        }
        
        else {
            let alert = UIAlertController(title: "텍스트가 올바르지 않습니다", message: "다시 써주세요", preferredStyle: .alert)
            let ok = UIAlertAction(title: "확인", style: .default)
            alert.addAction(ok)
            present(alert, animated: true)
        }
    }
    
    
    @IBAction func textfieldReturnTapped(_ sender: UITextField) {
        updateList()
    }
    
    @IBAction func okButtonTapped(_ sender: UIButton) {
        updateList()
        view.endEditing(true)
    }
}
TableViewCell.swift
import UIKit
class TodoTableViewCell: UITableViewCell {
    
    var specialCallBackMethod: (() -> Void)?
    var doneCallBackMethod: (() -> Void)?
    
    
    @IBOutlet var doneButton: UIButton!
    @IBOutlet var specialButton: UIButton!
    @IBOutlet var todoTextView: UITextView!
    
    
    func designCell(_ sender: ToDo) {
        
        doneButton.setImage(UIImage(systemName: (sender.done)
                                    ? "checkmark.square.fill"
                                    : "checkmark.square")
                                    , for: .normal)
        specialButton.setImage(UIImage(systemName: (sender.special)
                                      ? "star.fill"
                                       : "star")
                               , for: .normal)
        
        todoTextView.text = sender.main
    }
    
    
    
    @IBAction func specialButtonTapped(_ sender: UIButton) {
        specialCallBackMethod?()
    }
    
    @IBAction func doneButtonTapped(_ sender: UIButton) {
        doneCallBackMethod?()
    }
    
}
Movie List

ViewController
import UIKit
class BookViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource {
    
    
    @IBOutlet var bookCollectionView: UICollectionView!
    @IBOutlet var bookTableView: UITableView!
    
    
    var data = MovieInfo().movie
    
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "요즘 인기 작품"
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: Cell.BookTableViewCell.rawValue) as! BookTableViewCell
        
        cell.designCell(data[indexPath.row])
        
        
        cell.heartCallBackMethod = { [weak self] in
            self?.data[indexPath.row].like.toggle()
            
            self?.bookTableView.reloadData()
            self?.bookCollectionView.reloadData()
        }
        
        return cell
    }
    
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.filter { $0.like }.count    
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Cell.BookCollectionViewCell.rawValue, for: indexPath) as! BookCollectionViewCell
        
        cell.designCell(data.filter { $0.like }[indexPath.row] )
        
        cell.heartCallBackMethod = { [weak self] in
            
            
            
            
            
            
            
            let title = self?.data.filter{ $0.like }[indexPath.row].title 
            
            for i in 0...(self?.data.count)! - 1 {
                if title == self?.data[i].title {
                    self?.data[i].like.toggle()
                }
            }
            
            
            
            
            self?.bookCollectionView.reloadData()
            self?.bookTableView.reloadData()
            
            self?.configureCollectionViewLayout()
        }
        return cell
    }
    
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let vc = storyboard?.instantiateViewController(withIdentifier: Cell.DetailViewController.rawValue) as! DetailViewController
        
        vc.contents = data[indexPath.row]
        
        let nav = UINavigationController(rootViewController: vc)
        
        nav.modalPresentationStyle = .fullScreen
        
        present(nav, animated: true)
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let vc = storyboard?.instantiateViewController(withIdentifier: Cell.DetailViewController.rawValue) as! DetailViewController
        
        vc.contents = data.filter{ $0.like }[indexPath.row]
        
        let nav = UINavigationController(rootViewController: vc)
        
        nav.modalPresentationStyle = .fullScreen
        
        present(nav, animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        let nib = UINib(nibName: Cell.BookTableViewCell.rawValue, bundle: nil)
        bookTableView.register(nib, forCellReuseIdentifier: Cell.BookTableViewCell.rawValue)
        
        let nib2 = UINib(nibName: Cell.BookCollectionViewCell.rawValue, bundle: nil)
        bookCollectionView.register(nib2, forCellWithReuseIdentifier: Cell.BookCollectionViewCell.rawValue)
        
        
        bookCollectionView.dataSource = self
        bookCollectionView.delegate = self
        
        bookTableView.dataSource = self
        bookTableView.delegate = self
        
        configureCollectionViewLayout()
        bookTableView.rowHeight = 150
    }
    
    
    
    
    func configureCollectionViewLayout() {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.itemSize = CGSize(width: 100, height : 150)
        layout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
        
        bookCollectionView.collectionViewLayout = layout
    }
}
TableViewCell
import UIKit
class BookTableViewCell: UITableViewCell {
    
    var heartCallBackMethod: ( () -> Void )?
    
    @IBOutlet var posterImageView: UIImageView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var heartButton: UIButton!
    @IBOutlet var subLabel: UILabel!
    
    func designCell(_ sender: Movie) {
        posterImageView.image = UIImage(named: sender.title)
        posterImageView.contentMode = .scaleAspectFit
        
        titleLabel.text = sender.title
        
        subLabel.text = "\(sender.releaseDate) | \(sender.rate)"
        
        heartButton.setImage(UIImage(systemName: (sender.like) ? "heart.fill" : "heart"),
                             for: .normal)
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
    }
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
    }
    
    
    
    @IBAction func heartButtonTapped(_ sender: UIButton) {
        heartCallBackMethod?()
    }
}