Search code examples
swiftuicollectionviewuicollectionviewcelluicollectionreusableview

swift UICollectionView showing empty sometimes bug even header


I have a UIcollectionView that has a header and Footer and sometimes a weird bug just shows the screen empty. It is strange because even on the View Debugger it shows as empty but the Header is a static image that is on the app not something is getting from API and that does not show either.

Also the console does not give any errors methods. I try going to another view and forcing a reloadData() but still does not show anything. Any way I can debug this better or make sure it does not happen?

This is how the view debugger looks like:

this is how the view debugger looks like

You can see the header and footer empty reusable views:

you can see the header and footer empty

Edit:

This is how the supplementary views are being created using RxDataSources

 dataSource.supplementaryViewFactory = { (dataSource, collectionView, kind, indexPath) in
        switch kind {
        case UICollectionElementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: CellReuseId.contentHeaderCollectionView, for: indexPath ) as! ContentHeaderView
            headerView.imageView.image = ImageAssets.contentBanner
            let tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(self.showListOfEvents(_:)))
            headerView.addGestureRecognizer(tapGestureRecognizer)
            return headerView

        case UICollectionElementKindSectionFooter:
            let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: CellReuseId.contentFooterCollectionView, for: indexPath) as! ContentFooterView
            footerView.setUpObjects()
            //setUp Appropiate label or animation
            let showFooter: Bool = !(self.centerActivityIndicator?.isAnimating ?? false)
            footerView.setUpAppropiateDependingOnResults(isThereMoreResults: self.isThereMoreResults, showFooter: showFooter)
            return footerView
        default: break
        }
        //return default
        return UICollectionReusableView()
    }

And this is the code that gets the models for the API and binds them to the collectionView

let results = Observable.of(paginationObserver, offlineObserver).merge()
    //calls method that calls DB with the appropiate data
        .flatMapLatest { [unowned self] parametersChanged -> Driver<LecturesStateResults> in
            //since this is being called again, we make sure to clean out "old cache data" on view model
            self.videoObject.lecturesResults.value.removeAll(keepingCapacity: true)
            return self.setupLectures().asDriver(onErrorJustReturn: LecturesStateResults.empty)
        }

    results
        //Bind the result observable to the UIcollectionView
        //UiCollection view only wants an array not an Observable
        .map {
            if !$0.results.isEmpty { self.centerActivityIndicator?.stopAnimating()}
            return [SectionModel(model: "", items: $0.results)]
        }
        .bind(to: lectureViewSquare.rx.items(dataSource: dataSource))
        .addDisposableTo(disposeBag)

    lectureViewSquare.rx.setDelegate(self)
        .addDisposableTo(disposeBag)

Solution

  • I had the same problem with the same ui rendering, but without using RxSwift.

    The code that fixed the issue was

    dispatch_async(dispatch_get_main_queue(), ^{
          [self.collectionView reloadData];
    });