调用`reloadItems(at:)`导致程序崩溃

时间:2018-07-18 21:37:17

标签: ios swift uicollectionview uicollectionviewcell uicollectionreusableview

我正在尝试创建一个程序,当用户在UITextField中输入文本时,该程序会动态更新collectoinView。以下是我为实现此目的而创建的扩展名

我已根据您的建议更新了代码,以包含插入和删除语句,但是我仍在重构和添加委派过程中,但是虽然代码不会导致错误,但不允许用户继续输入并关闭键盘,如果我正确执行了所有操作

更新#2 (感谢您的所有帮助)

import UIKit

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UICollectionViewDelegate, UISearchBarDelegate {

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.delegate = self
        cv.dataSource = self
        return cv
    }()

    var genericTagsArray:[String] = ["tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za","tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za"]

    var currentTagsArray:[String] = [String]() {
        didSet {
            collectionView.reloadData()
        }
    }



    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(collectionView)
        collectionView.register(Cell.self, forCellWithReuseIdentifier: "cell")
        collectionView.register(Header.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header")
        collectionView.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: self.view.leadingAnchor, bottom: self.view.bottomAnchor, trailing: self.view.trailingAnchor, padding: .init(top: 30, left: 0, bottom: 30, right: 0))
        collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)


    }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return currentTagsArray.count
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
        cell.label.text = currentTagsArray[indexPath.item]
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header", for: indexPath) as! Header
        header.searchBar.delegate = self
        return header
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.contentSize.width, height: 75)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: self.view.frame.size.width, height: 50)

    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        self.currentTagsArray = self.genericTagsArray.filter { (text) -> Bool in
            return text.contains(searchText.lowercased())
        }
    }
}

class Cell : UICollectionViewCell {

    let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews() {
        self.backgroundColor = .gray
        self.addSubview(label)
        label.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
    }

}

class Header: UICollectionReusableView{

    var searchBar = UISearchBar(frame: .zero)

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews() {
        self.backgroundColor = .gray
        self.addSubview(searchBar)
        searchBar.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: nil, trailing: self.trailingAnchor, padding: .init(top: 0, left: 5, bottom: 0, right: 5), size: .init(width: 0, height: 50))
    }
}

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}

具有编辑功能的更新功能

    @objc func textFieldDidChange(){
        guard(!(feedSearchBar.text?.isEmpty)!) else{
            VC.currentTagsArray = VC.genericTagsArray
            VC.feedScreenCollectionView.reloadData()
            return
        }
        VC.currentTagsArray = VC.genericTagsArray.filter({letter -> Bool in
            if feedSearchBar.text!.count > letter.count{
                return false
            }
            let stringRange = letter.index(letter.startIndex, offsetBy: feedSearchBar.text!.count)
            let subword = letter[..<stringRange]
            return subword.lowercased().contains(feedSearchBar.text!.lowercased())
        })

        if VC.currentTagsArray.isEmpty{
            VC.feedScreenCollectionView.deleteItems()
            VC.currentTagsArray.insert(feedSearchBar.text!, at: 0)           
            VC.feedScreenCollectionView.insertItems(at: [IndexPath(item: 0, section: 0)])
            //VC.feedScreenCollectionView.reloadItems(inSection: 0)           
           // VC.feedScreenCollectionView.reloadItems(at: [IndexPath(item: 0, section: 0)])
        }
      //VC.feedScreenCollectionView.reloadData()
     VC.feedScreenCollectionView.reloadItems(inSection: 0)
   }

extension UICollectionView{
    func reloadItems(inSection section:Int = 0) {
        var indicies:[IndexPath] = [IndexPath]()
        print("current number of items to reload \(self.numberOfItems(inSection: section))")
        for i in 0..<self.numberOfItems(inSection: section){
        indicies.append(IndexPath(item: i, section: section))
            print("current item number: \(i)")
        }
        self.reloadItems(at: indicies)
       // self.insertItems(at: indicies)
    }

    func deleteItems(inSection section:Int = 0){
        var indicies:[IndexPath] = [IndexPath]()
        for i in 0..<self.numberOfItems(inSection: section){
            indicies.append(IndexPath(item: i, section: section))
        }
        self.deleteItems(at: indicies)
    }
}

原始功能:

extension UICollectionView{
        func reloadItems(inSection section:Int = 0) {
            var indicies:[IndexPath] = [IndexPath]()
            for i in 0..<self.numberOfItems(inSection: section){
            indicies.append(IndexPath(item: i, section: section))
            }
            self.reloadItems(at: indicies)
        }
    }

但是,无论何时我在编辑textField之后调用此函数,程序都会因错误而崩溃

  

*-[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:],/ BuildRoot / Library / Caches / com.apple.xbs / Sources / UIKit_Sim / UIKit-3698.54.4 / UICollectionView.m:5867中的断言失败   2018-07-18 16:28:02.226606-0400 FeedScreenReuseableView [87752:9704142] * 由于未捕获的异常'NSInternalInconsistencyException'终止了应用程序,原因:'试图将第6项插入第0节,但只有6个更新后的第0部分中的项目”

我不确定如何解决此问题。有没有更好的方法来重新加载不影响标题的单元格。谢谢您提前提供的所有帮助。以下是该项目的全部代码。

import UIKit

class ViewController: UIViewController,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate,UICollectionViewDataSource,printDelegateWorkedDelegate,updateCollectionView{

    func updateCollectionView() {
        self.feedScreenCollectionView.reloadData()
    }

    func printDelegateWorkedDelegate() {
        print("The delegate worked")
    }

    var genericTagsArray:[String] = ["tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za","tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za"]
    var currentTagsArray:[String] = [String]()
    var tagsSelected:[String] = [String]()
    let keyboardSlider = KeyboardSlider()

    var header:feedViewHeader = feedViewHeader()

    @IBOutlet weak var feedScreenCollectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        keyboardSlider.subscribeToKeyboardNotifications(view: view)
        currentTagsArray = genericTagsArray

        let viewTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(feedViewHeader.viewTapped(gestureRecognizer:)))
        viewTapGestureRecognizer.cancelsTouchesInView = false
        self.feedScreenCollectionView.addGestureRecognizer(viewTapGestureRecognizer)

        feedScreenCollectionView.delegate = self
        //
        feedScreenCollectionView.dataSource = self
        //

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 5, left: 1, bottom: 0, right: 1)
        layout.minimumLineSpacing = 0
        layout.headerReferenceSize = CGSize(width: 50, height: 75)

        layout.sectionHeadersPinToVisibleBounds = true
        feedScreenCollectionView.collectionViewLayout = layout
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
            return CGSize(width: 50, height: 75)
    }
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
                header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "feedViewHeader", for: indexPath) as! feedViewHeader
            header.VC = self
        return header

    }
    //


    //Data Source
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return currentTagsArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "feedViewCell", for: indexPath) as! feedViewCell
        cell.feedImageView.backgroundColor = .blue
        cell.feedImageView.clipsToBounds = true
        cell.feedImageView.layer.cornerRadius = CGFloat((cell.feedImageView.frame.width)/5)
        cell.feedLabel.text = currentTagsArray[indexPath.item]
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat{
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let collectionViewWidth = collectionView.bounds.width/4.0
        let collectionViewHeight = collectionViewWidth
        return CGSize(width: collectionViewWidth-4, height: collectionViewHeight+25)
    }
    var lastContentOffset:CGFloat = 0

    func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if self.lastContentOffset > self.feedScreenCollectionView.contentOffset.y && self.feedScreenCollectionView.contentOffset.y > 0 && self.feedScreenCollectionView.contentOffset.y < self.feedScreenCollectionView.frame.maxY {
            self.lastContentOffset = scrollView.contentOffset.y
            header.isHidden = false
        }
        else if (self.lastContentOffset < self.feedScreenCollectionView.contentOffset.y) && (self.feedScreenCollectionView.contentOffset.y < self.feedScreenCollectionView.frame.maxY) && (self.feedScreenCollectionView.contentOffset.y > 0)  {
            print("you scrolled down,content offSet: \(scrollView.contentOffset.y)->\(self.feedScreenCollectionView.contentOffset.y)")
            header.isHidden = true
        }
        else{
            self.lastContentOffset = scrollView.contentOffset.y
            print("content offSet: \(scrollView.contentOffset.y)")
            print("Nothing happened")
            //  self.headerDelegate?.hideHeaderView(hide: true)
        }


    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    var offsetY:CGFloat = 0

    @objc func keyboardFrameChangeNotification(notification: Notification) {
    }


}


class feedViewCell:UICollectionViewCell{

    @IBOutlet weak var feedImageView: UIImageView!
    @IBOutlet weak var feedLabel: UILabel!

    let keyboardSlider = KeyboardSlider()

    override func awakeFromNib() {
        super.awakeFromNib()
        feedLabel.translatesAutoresizingMaskIntoConstraints = false
        feedImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        feedImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        feedImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        feedImageView.bottomAnchor.constraint(equalTo: self.feedLabel.topAnchor).isActive = true

        feedImageView.translatesAutoresizingMaskIntoConstraints = false
        feedLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        feedLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        feedLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        feedLabel.topAnchor.constraint(equalTo: self.feedImageView.bottomAnchor).isActive = true
        feedLabel.textAlignment = .center

    }

}




class feedViewHeader:UICollectionReusableView,UITextFieldDelegate,UICollectionViewDelegate{

    @IBOutlet weak var feedSearchBar: UITextField!

    var delegateWorked:printDelegateWorkedDelegate?
    var updateCV:updateCollectionView?


    var VC:ViewController!
    var collectionView:UICollectionView?
    var stringToBeSet = "String to be set"

    override func awakeFromNib() {
        super.awakeFromNib()

        feedSearchBar.delegate = self
        feedSearchBar.autocorrectionType = .no
        feedSearchBar.keyboardType = .default
          feedSearchBar.addTarget(self, action: #selector(feedViewHeader.textFieldDidChange), for: .editingChanged)
        self.feedSearchBar.borderStyle = .roundedRect
        self.feedSearchBar.layer.borderColor = UIColor.black.cgColor
        self.feedSearchBar.layer.borderWidth = 4
        var searchBarHeight = self.feedSearchBar.bounds.height
        self.feedSearchBar.placeholder = "Tap To Search"
        self.feedSearchBar.returnKeyType = .search
        self.feedSearchBar.rightViewMode = .always
    }


    @objc func viewTapped(gestureRecognizer:UIGestureRecognizer){

        if  feedSearchBar.isFirstResponder{
            feedSearchBar.resignFirstResponder()
        }
    }

   func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
     VC.feedScreenCollectionView.reloadData()

    //VC.feedScreenCollectionView.reloadSections([0])
    return true
    }

    /// Helper to dismiss keyboard
    @objc func didStopEditing() {
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut)
        UIView.animate(withDuration: 0.2) {
            self.VC.view.frame.origin.y = 0
        }
    }
    @objc func textFieldDidChange(){
        guard(!(feedSearchBar.text?.isEmpty)!) else{
            VC.currentTagsArray = VC.genericTagsArray
            VC.feedScreenCollectionView.reloadData()
            return
        }

        VC.currentTagsArray = VC.genericTagsArray.filter({letter -> Bool in
           if feedSearchBar.text!.count > letter.count{
                return false
            }
            let stringRange = letter.index(letter.startIndex, offsetBy: feedSearchBar.text!.count)
            let subword = letter[..<stringRange]
            return subword.lowercased().contains(feedSearchBar.text!.lowercased())

        })

        if VC.currentTagsArray.isEmpty{
            VC.currentTagsArray.insert(feedSearchBar.text!, at: 0)
        }
    VC.feedScreenCollectionView.reloadItems(inSection: 0)
   }
}

extension Notification.Name{
    static let showKeyboard = Notification.Name("showKeyboard")
}
class KeyboardSlider: NSObject {
    // variables to hold and process information from the view using this class
    weak var view: UIView?

    @objc func keyboardWillShow(notification: NSNotification) {
        // method to move keyboard up
        // view?.frame.origin.y = 0 - getKeyboardHeight(notification as Notification)
        print("made it to keyboard will show")
    }

    func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        // get exact height of keyboard on all devices and convert to float value to return for use
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
        return keyboardSize.cgRectValue.height
    }

    func subscribeToKeyboardNotifications(view: UIView) {
        // assigning view to class' counterpart
        self.view = view
        // when UIKeyboardWillShow do keyboardWillShow function
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
    }

    func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
    }
}

class blankView:UICollectionReusableView{

}

extension UICollectionView{
    func reloadItems(inSection section:Int = 0) {
        print("made it to reload")
        for i in 0..<self.numberOfItems(inSection: section){
        self.reloadItems(at: [IndexPath(item: i, section: section)])
        }
    }
}

2 个答案:

答案 0 :(得分:3)

您正在向VC.currentTagsArray中添加新字符串,但是没有在集合视图中调用insertItems(at:),因此,当numberOfItemsInSection突然开始返回比以前更多的项目时,您会得到一致性异常。

关于风格的其他一些观察:

  • 我将使用委托将事件传递回视图控制器,而不是让标头视图和保留对VC的引用并紧密耦合对象的单元格。
  • 变量VC应该是vc。大写的第一个字母是一类
  • 只需将其命名为currentTags而不是currentTagsArray

答案 1 :(得分:1)

您的问题是因为您仅在调用insertItemsAt时才插入项目。您忘记了deleteItemsAt,它将删除所有您不想再显示的项目。

顺便说一句,您应该真正考虑重构代码。它不容易阅读,并且没有在正确的位置完成操作。例如,您的标头绝不能是负责更新您的收藏夹视图的标头。您应该将其留给控制器本身,并使用委托从头到视图控制器获取文本。

更新

这里是搜索您的完整代码。这只是一个示例,因此您可以了解如何实现。

import UIKit

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UICollectionViewDelegate, UISearchBarDelegate {

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.delegate = self
        cv.dataSource = self
        return cv
    }()

    var genericTagsArray:[String] = ["tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za","tag1","tag2","tag3","tag4","tag5","tag6","tag7","tag8","tag9","tag10","tag11","tag12","A","B","C","D","E","F","G","Ab","Abc","za"]

    var currentTagsArray:[String] = [String]() {
        didSet {
            collectionView.reloadSections(IndexSet.init(integer: 1))
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(collectionView)
        collectionView.register(Cell.self, forCellWithReuseIdentifier: "cell")
        collectionView.register(Header.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header")
        collectionView.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: self.view.leadingAnchor, bottom: self.view.bottomAnchor, trailing: self.view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 0))
        collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)


    }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if section == 0 { return 0 }
        return currentTagsArray.count
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header", for: indexPath) as! Header
        header.searchBar.delegate = self
        return header
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        if section == 0 {
            return CGSize(width: self.view.frame.width, height: 50)
        }
        return CGSize()
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
        cell.label.text = currentTagsArray[indexPath.item]
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: self.view.frame.size.width, height: 50)

    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        self.currentTagsArray = self.genericTagsArray.filter { (text) -> Bool in
            return text.contains(searchText.lowercased())
        }
    }
}

class Cell : UICollectionViewCell {

    let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews() {
        self.backgroundColor = .gray
        self.addSubview(label)
        label.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
    }

}

class Header : UICollectionViewCell {

    let searchBar = UISearchBar()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews() {
        self.backgroundColor = .gray
        self.addSubview(searchBar)
        searchBar.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
    }

}

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}