Mohamad Hassan Hijab
Mohamad Hassan Hijab

Reputation: 11

collectionview inside popup window

I am trying to use a collection view inside a popup window. The cell's data will be taken from an array and from pre-added data (image and text) inside the application. I tried to create a custom collection view swift class and try to add it inside popup window swift class but didn't work and gives me a fatal error when I tried to put it inside the view.addsubview(). Any ideas on how to do it to be able to insert the collection view inside a popup window?

Update: Code below

import UIKit

protocol PopUpDelegate {
    func handleDismissal()
}

class PopUpWindow: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellid, for: indexPath) as! TeamCell
        cell.backgroundColor = .cyan
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: (self.frame.width / 3) - 16, height: 100)
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }
    
    

    // MARK: - Properties
    
    let cellid = "cellid"
    
    let label: UILabel = {
        let label1 = UILabel()
        label1.translatesAutoresizingMaskIntoConstraints = false
        label1.text = "Tawasol Message"
        label1.textColor = .black
        label1.textAlignment = .center
        label1.backgroundColor = UIColor.red
        return label1
    }()
    
    let collectionview: UICollectionView = {
       let layout = UICollectionViewFlowLayout()
       let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        cv.register(TeamCell.self, forCellWithReuseIdentifier: "cellid")
       //If you set it false, you have to add constraints.
       cv.translatesAutoresizingMaskIntoConstraints = false
//       cv.delegate = self
//       cv.dataSource = self
//       cv.register(HeaderCell.self, forCellWithReuseIdentifier: "HeaderCell")
       cv.backgroundColor = .yellow
       return cv
    }()
    
    let col: MyViewController = {
       let coll = MyViewController()
        
        return coll
    }()
    
    let button: UIButton = {
        let button = UIButton(type: .system)
        button.backgroundColor = UIColor.blue
        button.setTitle("Done", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.addTarget(self, action: #selector(handleDismissal), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.layer.cornerRadius = 5
        return button
    }()
    
//    var delegate: PopUpDelegate?
    
    // MARK: - Init
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        
        addSubview(label)
        label.heightAnchor.constraint(equalToConstant: 50).isActive = true
        label.leftAnchor.constraint(equalTo: leftAnchor, constant: 12).isActive = true
        label.topAnchor.constraint(equalTo: topAnchor, constant: 12).isActive = true
        label.rightAnchor.constraint(equalTo: rightAnchor, constant: -12).isActive = true
        
        
        addSubview(col as! UICollectionView)
        
        addSubview(button)
        button.heightAnchor.constraint(equalToConstant: 50).isActive = true
        button.leftAnchor.constraint(equalTo: leftAnchor, constant: 12).isActive = true
        button.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12).isActive = true
        button.rightAnchor.constraint(equalTo: rightAnchor, constant: -12).isActive = true

    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Selectors
    
    @objc func handleDismissal() {
        print("DONE...")
//        delegate?.handleDismissal()
    }
    
}
class TeamCell: UICollectionViewCell{
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    func setup(){
        self.backgroundColor = .red
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

I created in another swift file the collectionView as a Subclass of UICollectionView and the code is below:

import UIKit

class MyViewController : UIViewController {
    var myCollectionView:UICollectionView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let view = UIView()
        view.backgroundColor = .white
        
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
        layout.itemSize = CGSize(width: 60, height: 60)
        
        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)

        myCollectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
        myCollectionView?.backgroundColor = UIColor.white
        
        myCollectionView?.dataSource = self
        myCollectionView?.delegate = self
 
        view.addSubview(myCollectionView ?? UICollectionView())
        
        self.view = view
    }
}

extension MyViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 9 // How many cells to display
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)
        myCell.backgroundColor = UIColor.blue
        return myCell
    }
}

extension MyViewController: UICollectionViewDelegate {
 
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
       print("User tapped on item \(indexPath.row)")
    }
}

The error is given when I want to show the popup window. The error is shown in init of the popUp swift file, in addSubview(col as! UICollectionView), the error is:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Upvotes: 0

Views: 772

Answers (1)

Vadim Belyaev
Vadim Belyaev

Reputation: 2859

The crash occurs because you're trying to force cast your col variable to UICollectionView, however it is declared as MyViewController here:

let col: MyViewController = {
       let coll = MyViewController()
        
        return coll
    }()

Assuming that you are not using a storyboard and doing everything in code, then in order to display some screen as a popup, I recommend doing the following:

  1. Create a separate view controller that will display your popup content.
  2. Add the view you want to present in a popup as a subview of that view controller's view.
  3. In your presenting view controller, create an instance of this new view controller and set its desired modal presentation style by setting the modal view controller's modalPresentationStyle property.
  4. Call the presenting view controller's present(_:animated:completion:) method, passing an instance of your modal view controller as an argument.

Upvotes: 0

Related Questions