1
votes

I am trying to display Data in a UICollectionView which worked perfectly exactly like i did in the whole app but for some reason, its not working in this case :

Here is the code needed to understand the issue :

SomeController :

func showContactsView(sender: RoundButton) -> Void {
        DispatchQueue.main.async {
            self.someView = SomeView()
            self.view.addSubview(self.someView)
            self.someView.setSomeViewViewConstraints(container: 
    self.view)
            self.someView.alpha = 0.0
            self.someView.contactsCollectionView.delegate = self
            self.someView.contactsCollectionView.dataSource = self
            self.someView.tabControlCallbacks["contacts"] = self.searchContacts
        }
    }

The controller init the view which contains the UICollectionView. This part is handled by autolayout and constraints, i have no issue whit it. It also inherits from UIColleCtionViewDelegate and UICollectionViewDataSource. :

class SomeController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate

The view init the collectionView and is displayed by a SegmentedControl which works perfectly :

private func initCollectionViews() {
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        layout.itemSize = CGSize(width: 50, height: 50)

        contactsCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        contactsCollectionView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
        contactsCollectionView.showsVerticalScrollIndicator = false
        contactsCollectionView.showsHorizontalScrollIndicator = false
        contactsCollectionView.register(AModelCollectionViewCell.self, forCellWithReuseIdentifier: "ContactsSelectModelCell")
        contactsCollectionView.translatesAutoresizingMaskIntoConstraints = false


        // Constraints to add when view is set dynamically
        contactsCollectionViewConstraints["leading"] = NSLayoutConstraint(item: contactsCollectionView, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0)
        contactsCollectionViewConstraints["trailing"] = NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal, toItem: contactsCollectionView, attribute: .trailing, multiplier: 1.0, constant: 0.0)
        contactsCollectionViewConstraints["top"] = NSLayoutConstraint(item: tabControl, attribute: .bottom, relatedBy: .equal, toItem: contactsCollectionView, attribute: .top, multiplier: 1.0, constant: 0.0)
        contactsCollectionViewConstraints["bottom"] = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: contactsCollectionView, attribute: .bottom, multiplier: 1.0, constant: 0.0)
    }

and the display by the segmented Control on value changed :

func cleanViews() {
        if self.contactsCollectionView.superview != nil {
            self.contactsCollectionView.removeFromSuperview()
        }
        if self.favoritesCollectionView.superview != nil {
            self.favoritesCollectionView.removeFromSuperview()
        }
    }

func bounce() {
        self.cleanViews()
        switch self.actualControl {
        case -1:
            break
        case 0:
            // Some code
        case 1:
            self.addSubview(self.contactsCollectionView)
            for constraint in self.contactsCollectionViewConstraints {
                self.addConstraint(constraint.value)
            }
            if let callback = self.tabControlCallbacks["contacts"]! {
                callback()
            }
        default:
            fatalError("Unknown control")
        }
    }

    // Selectors UISegmentedControl
    func valueChanged(sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == actualControl {
            tabControl.isMomentary = true
            sender.selectedSegmentIndex = -1
            tabControl.isMomentary = false
        }
        actualControl = sender.selectedSegmentIndex


        DispatchQueue.main.async {
            self.bounce()
        }
    }

As you can see i am setting a callback from the controller to the view in order to execute an action to my network and get the data to display on the collectionView. Here are the methods in the controller :

  //Collection Views Actions/Callbacks for selectContactsView
    func searchContacts() -> Void {
        let params : [String:Any] = [
            "id" : "-1",
            "name_begin" : ""
        ]

        self.network?.get(......, callback: afterSearchContacts)
    }

    func afterSearchContacts() -> Void {

        DispatchQueue.main.async {

            self.contactsSearchResults.removeAll()
            let usersData : [[String:Any]] = self.network?.lastResponse!["users"] as! [[String:Any]]
            let groupsData : [[String:Any]] = self.network?.lastResponse!["groups"] as! [[String:Any]]

            for userData in usersData {
                self.contactsSearchResults.append(User(fromData: userData))
            }
            for groupData in groupsData {
                self.contactsSearchResults.append(Group(fromData: groupData))
            }
            self.contactsView.contactsCollectionView.reloadData()
        }
    }

The reloadData is not working. Here are the methods of delegates and datasource before explaining which part is working and which is not :

//MARK: - UICollectionViewDataSource
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {


        switch self.contactsView.actualControl {
        case 1:

            if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ContactsSelectModelCell", for: indexPath) as? AModelCollectionViewCell {
                cell.model = contactsSearchResults[indexPath.item]
                cell.fillCell()
                return cell
            }
        case 0:
                //some Code
                return cell
            }
        default:
            print("Unknown cell type")
        }
        fatalError("Unknown cell type")
    }

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

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let count = collectionView == contactsView.contactsCollectionView ? contactsSearchResults.count : favoritesSearchResults.count

        return count
    }

    //MARK: - UICollectionViewFlowLayoutDelegate
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 50.0, height: 50.0)
    }

I have a custom collection view cell which is working on other collectionViews so no problem with that. I also take care of differentiate the identifiers for all the different CollectionViews when i do the register. In this case, when i use breakpoints, the number of items in section is > 0 but when i do the reloadData in the main thread after my network set the contactsSearchResult, it never go through the collectionView cellForItemAt.

Any idea?

1
When you say not working, what is exactly is happening? Is it going to the data source methods? Can you print contactsCollectionView and see if it is not nil. Also check if its datasource is not niladev
When i say not working, i mean that collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath) is never executed in this case. ContactsCollectionView is obviously not nil, same for datasource.Poulpy
Are you sure it is calling this line self.contactsView.contactsCollectionView.reloadData()? After that is it calling numberOfSections if you put breakpoint there?adev
I have tested this before and just tested again now. Unfortunately yes this is the case. I don't understand why collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath) is not called just after numberOfSections been updated. Also count in numberOfSections is exactly 6 after reloadData been called.Poulpy
Put breakpoint in swift self line and see if it is going there. Otherwise check if the datasource name is not misspelled. Also what is number of sections and what is number of items in each section? Is it correct?adev

1 Answers

-1
votes

For those who read this post, i have ended up by coding my own CollectionView. Working like a charm.