0
votes

I have an UITableView and I want to add a UICollectionView with a horizontal flow layout as subview in the backgroundView of the tableView, to do the same effect of the AppStore. Here I have the implementation code:

in the viewDidLoad:

UIView *tableViewBackgroundView = [[UIView alloc] initWithFrame:self.view.bounds];
    self.tableView.backgroundView = tableViewBackgroundView;

// HighlightView heightFactor returns the reason which is  9.0/16.0
    CGFloat headerViewHeight = CGRectGetWidth(self.view.frame) * [HighlightView heightFactor];
    self.tableView.contentInset = UIEdgeInsetsMake(headerViewHeight, 0, 0, 0);
    self.headerView = [[HighlightView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), headerViewHeight)];
    [tableViewBackgroundView addSubview:self.headerView];

The HighlightView is a view with a collectionView inside.

But I'm having an issue, when the user interacts with the collectionView I start to receive this log:

Please check the values return by the delegate. the behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.

And this becomes a loop that doesn't stop even when the user stops to interact.

HighlightView (CollectionView) code:

override init(frame: CGRect) {
    super.init(frame: frame)
    self.viewModel.delegate = self
    self.configureHighlightsCollectionView()
}

func configureHighlightsCollectionView() {

    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    flowLayout.minimumInteritemSpacing = 0
    flowLayout.minimumLineSpacing = 0
    if systemVersion > 8.0 {
        flowLayout.estimatedItemSize = self.frame.size
    }
    flowLayout.itemSize = self.frame.size
    self.highlightsCollectionView = UICollectionView(frame: self.bounds, collectionViewLayout: flowLayout)
    self.highlightsCollectionView.frame = self.bounds
    self.highlightsCollectionView.scrollsToTop = false
    self.highlightsCollectionView.pagingEnabled = true
    self.highlightsCollectionView.registerClass(CachedImageCollectionViewCell.self, forCellWithReuseIdentifier: "ImageCell")
    self.addSubview(self.highlightsCollectionView)

    self.highlightsCollectionView.invalidateIntrinsicContentSize()

    self.highlightsCollectionView.dataSource = self
    self.highlightsCollectionView.delegate = self
    self.highlightsCollectionView.backgroundColor = UIColor.greenColor()

    self.highlightsCollectionView.snp_makeConstraints { (make) -> Void in
        make.top.equalTo(self)
        make.bottom.equalTo(self)
        make.left.equalTo(self)
        make.right.equalTo(self)
    }

}
//Mark: UICollectionViewDataSource
    public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.viewModel.highlightsArray.count
    }

public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ImageCell", forIndexPath: indexPath) as! CachedImageCollectionViewCell
    cell.highlightData = self.viewModel.highlightsArray[indexPath.item]
    return cell
}

public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    println(self.frame.size)
    return self.frame.size
}

The viewModel is a class who controls the data flow of the collectionView.

1
Why not directly using the headerView property of your tableview ? If you're using Auto Layout you have to set constraints to your views. - GaétanZ
Because the animation effect, when you use the Header, it scrolls with the content, when you use as background, the content scrolls above of it. And yes, I've set the constrains, and even without any kind of auto layout, the problem happens - RodolfoAntonici
Sure. Anyway your problem comes from your UICollectionView and its layout, you should put some code about it - GaétanZ

1 Answers

1
votes

First I don't think it's a good idea to put your view as datasource and delegate of your UICollection inside your UIView subclass. You're not respecting the MVC pattern. Learn more informations about it at Introducing iOS Design Pattern . You should set your controller as it.

The problem is you're setting the itemSize of your UICollectionViewFlowLayout in initFrame: based on the frame of your view. In that method, the frame of your UIView is not correct since you're using AutoLayout. You have to wait until AutoLayout calculates the layouts of your views so when layoutSubviews: is called. Learn about UIView and AutoLayout in the Matt's book. It's for iOS 6 and in Objective - C but still great.