1

I am trying to add a activity indicator but I am not able to do so successfully because my collection view header is loading before viewdidload so therefore I have things showing before my activity indicator even starts. Can someone please help me or point me in the right direction. I have posted my code below

viewDidLoad

 override func viewDidLoad() {
        super.viewDidLoad()

           fetchUser()
   profileCollectionView?.register(guestHeaderCollectionViewCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerId")

   profileCollectionView?.register(photoViewCollectionViewCell.self, forCellWithReuseIdentifier: cellId)

}

   func fetchUser() {
        self.activityIndicator.startAnimating()

        if let uid = selectedUser.uid{

            Database.fetchUserWithUID(uid: uid) { (user) in
                self.selectedUser = user
                self.navigationItem.title = self.selectedUser?.fullName

                self.profileCollectionView?.reloadData()
                self.activityIndicator.stopAnimating()
                self.activityIndicator.isHidden = true
                self.fetchOrderedPosts()
            }
        }
    }

Collection view header thats being called before viewDidLoad

 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
       let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! guestHeaderCollectionViewCell

        header.user = self.selectedUser
        header.delegate = self

        return header
    }

view controller

class newGuestPhotoViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, guestProfileHeaderDelegate, HomePostCellDelegate {

    let cellId = "cellId"
    let homePostCellId = "homePostCellId"

    @IBOutlet weak var profileCollectionView: UICollectionView!
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    var user: userAccount?
    var selectedUser: userAccount!
    var posts = [Post]()    
    let stringID = NSUUID().uuidString   
    var isGridView = true

    func didChangeToGridView() {
        isGridView = true
        profileCollectionView?.reloadData()
    }

    func didChangeToListView() {
        isGridView = false
        profileCollectionView?.reloadData()
    }

    var showDataFlag : Bool = false!

    override func viewDidLoad() {
        super.viewDidLoad()

        fetchUser()
        profileCollectionView?.register(guestHeaderCollectionViewCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerId")       
        profileCollectionView?.register(photoViewCollectionViewCell.self, forCellWithReuseIdentifier: cellId)       
        profileCollectionView?.register(newsfeedCollectionViewCell.self, forCellWithReuseIdentifier: homePostCellId)
    }  
    func fetchUser() {
        self.activityIndicator.startAnimating()
        if let uid = selectedUser.uid{

            Database.fetchUserWithUID(uid: uid) { (user) in
                self.selectedUser = user
                self.navigationItem.title = self.selectedUser?.fullName
                self.showDataFlag = true;
                self.profileCollectionView?.reloadData()
                self.activityIndicator.stopAnimating()
                self.activityIndicator.isHidden = true
                self.fetchOrderedPosts()
            }
        }
    }

    fileprivate func fetchOrderedPosts() {
        guard let uid = selectedUser?.uid else { return }
        let ref = Database.database().reference().child("post").child(uid)
        ref.queryOrdered(byChild: "dateOfPost").observe(.childAdded, with: { (snapshot) in            
            guard let dictionary = snapshot.value as? [String: Any] else { return }            
            let uid = dictionary["postUserUID"] as? String

            Database.fetchUserWithUID(uid: uid!, completion: { (userSnap) in

            let post = Post(user:userSnap, dictionary: dictionary)           
            self.posts.insert(post, at: 0)
            guard let uid = Auth.auth().currentUser?.uid else {return}
            Database.database().reference().child("likes").child(post.postID!).child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
                print(snapshot)

                if let value = snapshot.value as? Int, value == 1 {
                    post.hasLiked = true
                } else {
                    post.hasLiked = false
                }

              DispatchQueue.main.async(execute: {
            self.profileCollectionView?.reloadData()
                })
            }, withCancel: { (err) in
                print("Failed to fetch like info for post:", err)
            })

            })
        }) { (err) in
            print("Failed to fetch ordered posts:", err)
        }
    }

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

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

        if isGridView {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! photoViewCollectionViewCell
            cell.post = posts[indexPath.item]

            return cell
        } else {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: homePostCellId, for: indexPath) as! newsfeedCollectionViewCell
            cell.post = posts[indexPath.item]
            cell.delegate = self

            return cell
        }
    }

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

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

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
       let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! guestHeaderCollectionViewCell

        header.user = self.selectedUser
        header.delegate = self

        return header
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: view.frame.width, height: 250)
    }
j.iese
  • 171
  • 2
  • 12
  • setup your profileCollectionView.datasource after, in your `viewDidAppear` for example, Or use a flag and `return 0` in your `UICollectionViewDataSource` method called `numberOfSectionsInCollectionView` and when you want change the flag to true and return the number of sections that you need – Reinier Melian Nov 16 '17 at 10:26
  • Thanks for the reply @ReinierMelian. Could you please elaborate more on using "a flag and ´return 0´ in your ´UICollectionViewDataSource´ method called ´numberOfSectionsInCollectionView". What do mean by flag? – j.iese Nov 16 '17 at 10:28

1 Answers1

1

As I said in mi comment, you can add a flag and after your fetchUser() you can set this flag true and your collectionView will show your data

something like this

var showDataFlag : Bool = false

override func viewDidLoad() {
        super.viewDidLoad()

           fetchUser()
   profileCollectionView?.register(guestHeaderCollectionViewCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerId")

   profileCollectionView?.register(photoViewCollectionViewCell.self, forCellWithReuseIdentifier: cellId)

}

   func fetchUser() {
        self.activityIndicator.startAnimating()

        if let uid = selectedUser.uid{

            Database.fetchUserWithUID(uid: uid) { (user) in
                self.selectedUser = user
                self.navigationItem.title = self.selectedUser?.fullName

                self.showDataFlag = true;
                self.profileCollectionView?.reloadData()
                self.activityIndicator.stopAnimating()
                self.activityIndicator.isHidden = true
                self.fetchOrderedPosts()
            }
        }
    }

//In your Collection View Data Source Implementation

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        if(!showDataFlag){
           return 0
        }
           return yourNeededNumberOfSections
    }
Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
  • ok it still doesn't work. For some strange reason my collection view header is still showing even if count returns 0. I forgot to mention the collections view is within a tab bar controller if that makes a difference – j.iese Nov 16 '17 at 10:44
  • @j.iese can you post your viewController full code? – Reinier Melian Nov 16 '17 at 10:45
  • Ok I've updated my question and added the view controller – j.iese Nov 16 '17 at 10:55
  • @j.iese your `var showDataFlag : Bool = false!` line throw a compilation error message for me, did you try removing the !? – Reinier Melian Nov 16 '17 at 11:03
  • Yes I removed ! but still no luck – j.iese Nov 16 '17 at 11:06
  • @j.iese check my answer again, is not `numberOfItemsInSection`the method that your need to implement is `numberOfSections` instead so change that and let me know must work – Reinier Melian Nov 16 '17 at 11:08
  • Ok thats solved the problem. Thank you for your help. Sorry I miss read your answer before – j.iese Nov 16 '17 at 11:17