airbnb / MagazineLayout

A collection view layout capable of laying out views in vertically scrolling grids and lists.
Apache License 2.0
3.3k stars 220 forks source link

Delegate not being triggered #37

Closed dfmarulanda closed 5 years ago

dfmarulanda commented 5 years ago

Describe the bug I created my CollectionView from the storyboard, connected to the Controller, added to the delegate; registered the MagazineLayoutCollectionViewCell, but delegate functions are not getting triggered.

dfmarulanda commented 5 years ago

Created the collectionView with code; it don't trigger the delegate methods:

  // UI
  private(set) lazy var collectionView: UICollectionView = {
    let layout = MagazineLayout()
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    collectionView.refreshControl = refreshControl
    collectionView.delegate = self
    collectionView.allowsSelection = false
    collectionView.isPrefetchingEnabled = true
    collectionView.contentInsetAdjustmentBehavior = .always
    collectionView.register(UINib.init(nibName: "ItemExploreViewCell", bundle: Bundle.main), forCellWithReuseIdentifier: "ItemExploreViewCell")
    refreshControl.tintColor = K.Colors.crw_purple
    return collectionView
  }()
bryankeller commented 5 years ago

@dfmarulanda make sure that your collection view has a non-zero width and height. Do you add constraints to it or set the frame manually? Make sure your constraints are correct.

dfmarulanda commented 5 years ago

I added the constraints using snap kit. Height width equal to super view and leading top to superview

On Thu, Apr 18, 2019, 12:50 AM Bryan Keller notifications@github.com wrote:

@Dfmarulanda https://github.com/Dfmarulanda make sure that your collection view has a non-zero width and height. Do you add constraints to it or set the frame manually? Make sure your constraints are correct.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/airbnb/MagazineLayout/issues/37#issuecomment-484365182, or mute the thread https://github.com/notifications/unsubscribe-auth/AAS2FQQ4NPQ7XS4NNGQLTLLPRAD2RANCNFSM4HGYI6RA .

bryankeller commented 5 years ago

Do you see the collection view in the view debugger? Have you set a breakpoint on collectionView.delegate = self to confirm that gets called? Is your UINib code actually initializing a valid object?

dfmarulanda commented 5 years ago

Yes. I have a breakpoint and its being triggered; but delegate methods are not. It could be something with my RxDataSource implementation?

//
//  ExploreViewController.swift
//  Crowdswap
//
//  Created by Daniel Marulanda on 11/15/18.
//  Copyright © 2018 Crowdswap, Inc. All rights reserved.
//

import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import RxGesture
import Kingfisher
import SkeletonView
import MagazineLayout
import SnapKit

class ExploreViewController: UIViewController {

  var viewModel: ExploreViewModel!
  let disposeBag = DisposeBag()
  let refreshControl = UIRefreshControl()

  // UI
  private(set) lazy var collectionView: UICollectionView = {
    let layout = MagazineLayout()
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    collectionView.backgroundColor = .white
    collectionView.refreshControl = refreshControl
    collectionView.delegate = self
    collectionView.allowsSelection = false
    collectionView.isPrefetchingEnabled = false
    collectionView.contentInsetAdjustmentBehavior = .always
    collectionView.register(UINib.init(nibName: "ItemExploreViewCell", bundle: Bundle.main), forCellWithReuseIdentifier: "ItemExploreViewCell")
    refreshControl.tintColor = K.Colors.crw_purple
    return collectionView
  }()

  // UI Cycle
  override func viewDidLoad() {
    super.viewDidLoad()

    //Autolayout
    self.view.addSubview(collectionView)
    collectionView.snp.makeConstraints { make in
      make.width.height.equalToSuperview()
      make.leading.top.equalToSuperview()
    }

  }

}

extension ExploreViewController: BindableType {
  func bindViewModel() {

    //Set CollectionView DataSource
    let (configureCollectionViewCell, configureSupplementaryView) = collectionViewDataSourceUI()
    let cvDataSource = RxCollectionViewSectionedAnimatedDataSource<ExploreSection>(
      configureCell: configureCollectionViewCell,
      configureSupplementaryView: configureSupplementaryView
    )

    collectionView.prepareSkeleton(completion: { _ in return })
    viewModel.items.asObservable()
      .bind(to: collectionView.rx.items(dataSource: cvDataSource))
      .disposed(by: disposeBag)
  }
}

extension ExploreViewController {
  func collectionViewDataSourceUI() -> (RxCollectionViewSkeletonedAnimatedDataSource<ExploreSection>.ConfigureCell, RxCollectionViewSkeletonedAnimatedDataSource<ExploreSection>.ConfigureSupplementaryView) {
    return (
      // swiftlint:disable:next identifier_name
      { [unowned self] (_, cv, ip, i) in
        let cell: ItemExploreViewCell = cv.dequeueReusableCell(for: ip)
        cell.bind(to: i)
        return cell
      },
      // swiftlint:disable:next identifier_name
      { (ds, cv, kind, ip) in

        let section: ItemExploreSectionView = cv.dequeueReusableSupplementaryView(ofKind: kind, for: ip)
        return section
      }
    )
  }
}

extension ExploreViewController: UICollectionViewDelegateMagazineLayout {

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeModeForItemAt indexPath: IndexPath) -> MagazineLayoutItemSizeMode {
    let width = MagazineLayoutItemWidthMode.fullWidth(respectsHorizontalInsets: true)
    let height = MagazineLayoutItemHeightMode.dynamic
    return MagazineLayoutItemSizeMode(widthMode: width, heightMode: height)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForHeaderInSectionAtIndex index: Int) -> MagazineLayoutHeaderVisibilityMode {
    return .visible(heightMode: .dynamic)

  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForFooterInSectionAtIndex index: Int) -> MagazineLayoutFooterVisibilityMode {
    return .visible(heightMode: .dynamic)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForBackgroundInSectionAtIndex index: Int) -> MagazineLayoutBackgroundVisibilityMode {
    return .hidden
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, horizontalSpacingForItemsInSectionAtIndex index: Int) -> CGFloat {
    return 16
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, verticalSpacingForElementsInSectionAtIndex index: Int) -> CGFloat {
    return 8
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForSectionAtIndex index: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 0, left: 8, bottom: 24, right: 8)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForItemsInSectionAtIndex index: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 24, left: 0, bottom: 24, right: 0)

  }
}
dfmarulanda commented 5 years ago

OK. When I create a DataSource manually from UICollectionViewDataSource it works as expected, so i think it seems to be something with the Rx Implementation

bryankeller commented 5 years ago

Thanks for the update @Dfmarulanda, I'm going to close this out since it sounds like it's unrelated to MagazineLayout. Feel free to post an update if you figure out what was wrong, it might be useful to someone else using Rx stuff!

dfmarulanda commented 5 years ago

Just use this as workaround extension _RXDelegateProxy: UICollectionViewDelegateMagazineLayout

chriskilpin commented 5 years ago

Hi Guys, I am facing the same issue. @Dfmarulanda How did you end up solving this? I tried your workaround but it complained about _RXDelegateProxy not implementing the delegate methods from UICollectionViewDelegateMagazineLayout.

Thanks in advance.

anonrig commented 5 years ago

hey @chriskilpin I'm facing the same issue ahaha. any solutions?

chriskilpin commented 5 years ago

hey @anonrig I did find a solution, made a gist for the delegate proxy I am using. https://gist.github.com/chriskilpin/20c08d2b81cd7a2df01fa008f5a08474 Use MagazineCollectionView instead of a normal collectionview because it seems RxCocoa only allows you to register one delegate per collectionview type. Then call MagazineLayoutDelegateProxy.registerImplementation() in your app delegate to register it.

anonrig commented 5 years ago

That's awesome! You rock @chriskilpin !