Search code examples
iosswiftfirebase-realtime-databaseuicollectionviewuisegmentedcontrol

How to fetch data based on selectedSegmentIndex


I am required to fetch data based on what cell a user selects. I started having issues when I integrated segmented control. When a user selects female/male. The home UI will change based on what index is selected on the segment control. The problem I am currently having is when a user does select a cell. I'm not sure if I am using the switch statement correctly or not but, however not post is being fetched. I even ensured in the database that every category has a dummy photo to fetch.

Here is the code for the home page which works fine but code may be relevant to some.

Code is edited based on answer below now

On didSelect I am getting an error now that states

Cannot assign value of type 'String' to type 'Trend?'

I thought by adding name to vc.trend would be able to fetch the data because before we even implemented segmentedControl, didSelect worked fine by just using the name of a trend, then we would fetch photos based on the trend name.

       case 0: vc.trend.name = femaleTrends[indexPath.row]
        case 1: vc.trend.name = maleTrends[indexPath.row]

   var selectedSegmentIndex = 0
   var header: HomeViewHeaderReusableView?


// Reload data when index changes
 func handleSegControlTapped(for header: HomeViewHeaderReusableView) {
        selectedSegmentIndex = header.segmentedControl!.selectedSegmentIndex
        collectionView.reloadData()
    }

   // Return the number of trend categories availabe
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {


        switch selectedSegmentIndex {
        case 0: return femaleTrends.count
        case 1: return maleTrends.count
        default: print("opps, cant load data")
           return 0
        }

    }

    //Display the current trend image place holder and labels
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "homeViewCell", for: indexPath) as! CurrentTrendsCell

        switch selectedSegmentIndex {
        case 0: cell.trendsLabel.text = femaleTrends[indexPath.row]
        cell.trendsImageView.image = femaleImages[indexPath.row]


        case 1: cell.trendsLabel.text = maleTrends[indexPath.row]
        cell.trendsImageView.image = maleImages[indexPath.row]

        default: break

        }

        return cell


    }


    // Selected HomeView Cell data will pass to second home view controller
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        let storyboard = UIStoryboard(name: "Main", bundle: nil)

        let vc = storyboard.instantiateViewController(withIdentifier: "selectedHomeCellView") as! SelectedCellHomeViewController

        switch selectedSegmentIndex {
        case 0: vc.trend = femaleTrends[indexPath.row]
        case 1: vc.trend = maleTrends[indexPath.row]
            default: break
        }

        self.navigationController?.pushViewController(vc, animated: true)

       self.navigationController?.navigationBar.backIndicatorImage = #imageLiteral(resourceName: "BackButton")
       self.navigationItem.backBarButtonItem = UIBarButtonItem(title: nil, style: UIBarButtonItem.Style.plain, target: nil, action: nil)

    }

This is the viewController code with the issue




   // Display uploaded photos
   func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return posts.count
   }

   // Get a photo cell
   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "userPhotos", for: indexPath) as! PostCollectionViewCell

       cell.posts = posts[indexPath.item]


       return cell
   }


var trend: Trend!


func fetchPosts() {
  print("fetching post")

   self.trendDetails = trend.details
   self.trendName = trend.name

  switch trend.gender  {

      case .female:
       FEMALE_TRENDS_REF.child((trend.childValue)).observe(.childAdded) { (snapshot) in
             let postId = snapshot.key
             Database.fetchPost(with: postId, completion: { (post) in
                 self.posts.append(post)
                 self.posts.sort(by: { (post1, post2) -> Bool in
                 return post1.creationDate > post2.creationDate
             })
             self.collectionView?.reloadData()
          })

   }


           case .male:
               MALE_TRENDS_REF.child((trend.childValue)).observe(.childAdded) { (snapshot) in
              let postId = snapshot.key
              Database.fetchPost(with: postId, completion: { (post) in
                  self.posts.append(post)
                  self.posts.sort(by: { (post1, post2) -> Bool in
                  return post1.creationDate > post2.creationDate
              })
              self.collectionView?.reloadData()

           })


     }

}

   }

 let femaleTrends = [

Trend(name: "Animal Prints", details: "girl prints", image: UIImage(named: "Animal Prints"), gender: .female, childValue: "animalprints"),


Trend(name: "Dark Romance", details: "Darkromance text.",image: UIImage(named: "Dark Romance"),gender: .female, childValue: "darkromance"),


Trend(name: "Green", details: "Green text.",image: UIImage(named: "Green"),gender: .female, childValue: "green"),]




    let maleTrends = [

Trend(name: "Animal Prints", details: "mens animal prints",image:UIImage(named: "Aprint"),gender: .male , childValue: "animalprints"),


Trend(name: "Corduroy", details: "mens corduroy",image: UIImage(named: "CorduroyM"),gender: .male, childValue: "corduroy"),


Trend(name: "Earth Tones", details: "mens earth tones",image: UIImage(named: "Earth Tones"),gender: .male, childValue: "earthtones"),

]

I basically want to fetch data based on the trend name and segmentIndex..


Solution

  • Your data model is inappropriate.

    You are strongly discouraged from using multiple arrays as data source.

    Declare a struct which contains all information of one item in the collection view and add an enum for the gender information.

    enum Gender { case male, female }
    
    struct Trend {
       let name : String
       let details : ...
       let image : ...
       let gender : Gender
       // other properties 
    }
    

    Populate the data model accordingly.

    Then pass one item to the detail view controller, the selected segment index is not needed.

    switch selectedSegmentIndex {
        case 0: vc.trend = femaleTrends[indexPath.row]
        case 1: vc.trend = maleTrends[indexPath.row]
        default: break
    }
    

    In the view controller with the issue declare a property

    var trend : Trend!
    

    and fetch the posts depending on the gender information

    func fetchPosts() {
       print("fetching post")
    
       self.trendDetails = trend.details ?? ""
       self.trendName = trend.name ?? ""
    
       switch trend.gender  {
    
           case .female:
               FEMALE_TRENDS_REF.child((trend.childValue)!).observe(.childAdded) { (snapshot) in
                  let postId = snapshot.key
                  Database.fetchPost(with: postId, completion: { (post) in
                      self.posts.append(post)
                      self.posts.sort(by: { (post1, post2) -> Bool in
                      return post1.creationDate > post2.creationDate
                  })
                  self.collectionView?.reloadData()
               })
           case .male:
               MALE_TRENDS_REF.child((trend.childValue)!).observe(.childAdded) { (snapshot) in
                   let postId = snapshot.key
                   Database.fetchPost(with: postId, completion: { (post) in
                       self.posts.append(post)
                       self.posts.sort(by: { (post1, post2) -> Bool in
                       return post1.creationDate > post2.creationDate
                   })
                   self.collectionView?.reloadData()
                })
          }
     }