0
votes

I have collectionViewCell constructed in IB. All constraints are set, but when collection view loads cells their dimensions are default 50x50.

Here is my cell:

enter image description here

Another interesting moment, if I set layout property for collection view like this:

layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize

It lays out cells properly but only after reload.

enter image description here

As you can see nothing shows after swipe left, but after pull and refresh cells appears. Why cells not appears after swipe and loads data? I figured out that datasource functions like numberOfItemsInSection, willDisplay, cellForItemAt are not called. They are called one after refresh.

This two screens(left & right) are cell of horizontal collection view. Inside second cell I have another collection view. Inside second cell I instantiate collection like so:

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    collectionView.backgroundColor = UIColor.clear
    collectionView.alwaysBounceVertical = true
    return collectionView
}()
...
override func setupViews() {
    super.setupViews()

    let nib = UINib(nibName: String(describing: WorkoutSectionCollectionViewCell.self), bundle: nil)
    collectionView.register(nib, forCellWithReuseIdentifier: String(describing: WorkoutSectionCollectionViewCell.self))
    collectionView.dataSource = self
    collectionView.delegate = self

    fetchMyWorkouts()
    collectionView.reloadData()
}

fetchMyWorkouts function retrieves data from backend by REST Api:

func fetchMyWorkouts() {
    self.activityIndicatorView.startAnimating()
    Synchronizer.sharedInstance.syncNewWorkout { (_, error) in
        if error != nil {
            let message = Murmur(title: error!.localizedDescription, backgroundColor: Colors.colorWhite, titleColor: Colors.colorCadmiumOrange, font: UIFont(name: "OpenSans", size: 10)!, action: nil)
            Whisper.show(whistle: message, action: .show(5))
        } else {
            RestApi.sharedInstance.fetchData(withRequest: .getWorkouts, entityNamed: .workout) { _ in
                DispatchQueue(label: "", qos: .background).async {
                    let requestMyWorkouts = NSFetchRequest<NSFetchRequestResult>(entityName: "Workout")
                    requestMyWorkouts.predicate = NSPredicate(format: "createdBy == %@", USERID)
                    do {
                        self.myWorkouts = try dataStack.mainContext.fetch(requestMyWorkouts) as! [Workout]
                    } catch {
                        fatalError("Failed to fetch workouts: \(error)")
                    }

                    DispatchQueue.main.async(execute: {
                        self.placeholderStackView.isHidden = (self.myWorkouts.count == 0) ? false : true
                        self.collectionView.reloadData()
                        self.activityIndicatorView.stopAnimating()
                    })
                }
            }
        }
    }
}

UPDATE: This is specific issue linked to fetchMyWorkouts() function. It didn't finish and datasource empty when collection view tried to fetch data for cell. As a result - nothing appears.

1

1 Answers

0
votes

Make sure to call reloadData on viewWillAppear or something similar, after you've fetched your data from your web service or anywhere you think suits best.

From Apple docs - reloadData on UICollectionView or UITableView:

Call this method sparingly when you need to reload all of the items in the collection view. This causes the collection view to discard any currently visible items (including placeholders) and recreate items based on the current state of the data source object.

So it basically calls those protocol functions.