Giter Site home page Giter Site logo

Comments (10)

pteasima avatar pteasima commented on August 28, 2024 1

Thanks for making this library.

While I agree that basing the size off of data rather than autolayout is preferrable and more performant, I think that not having an "intrinsicSizeSizeProvider" or similar greatly limits the usefulness of the whole library. With how autolayout heavy iOS code usually is, this is a must have feature for me.

Below is an example of a simple tableView like layout with dynamic cell height:

    @IBOutlet weak var collectionView: CollectionView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let provider = CollectionProvider(data: ["firstfdshafhjkdajkhfdhkjfdahjhkgjfdaghdfagkhjadfghkjfdaghkjdfghjkakghjadfkghjfadghkjfdahjkgashjgkfdhjgkdfsahjgkdfashjgkfadsghjkfadhjgkhjgkfahjkgaf", "second"], viewUpdater: { (label: UILabel, data: String, index: Int) in
            label.numberOfLines = 0
            label.text = data
            label.backgroundColor = index == 0 ? .red : .green
        })
        provider.sizeProvider = { [unowned provider] (index,_, collectionSize) in
            let v = provider.view(at: index)
            return CGSize(
                width: collectionSize.width,
                height: v.systemLayoutSizeFitting(CGSize(width: collectionSize.width, height: UILayoutFittingCompressedSize.height)).height
            )
        }
        collectionView.provider = provider
    }

The problem with this approach is that you have to do the whole [unowned] dance and have to split the initialization into multiple steps. Similar code is bound to be repeated in many apps that use CollectionKit, but there arent good ways to simplify it.

Making this a feature of CollectionKit would be quite simple, but requires API breaking changes (at the very least, making the CollectionProvider or the View a parameter of the SizeProvider function). I might make a PR if I find the time, but first I wonder how the author feels about this and if they have any suggestions for how the new API should look (or any strong arguments against adding this feature).

from collectionkit.

lkzhao avatar lkzhao commented on August 28, 2024 1

@pteasima
Using AutoLayout for each cell greatly impact the performance of collection view. Because collection view can have thousands of cells, CollectionView only initializes views that are on screen. You don't want to create thousands of views for getting the sizes when there are only a few that is displayed.

If we were to implement some way to use autolayout, we would be creating a dummy cell in the memory and use that to retrieve the size.

from collectionkit.

pteasima avatar pteasima commented on August 28, 2024 1

Thanks, I didnt realize that CollectionKit needs to calculate all sizes upfront. I can still imagine it might be possible to only calculate sizes lazily. I think UITable/CollectionView do this somehow. It would involve constantly updating the contentSize as the user scrolls and new cell sizes get calculated. Updating the contentSize could mess up scrolling etc. While I think its doable (and I believe apple does this), its a hard problem and not one that can be solved without vast changes to the whole library. So, as I said, I give up and consider this matter closed ;)

Also, I see the benefit of your "prototype cell" solution over mine, but as you said its still not nearly performant enough.

from collectionkit.

jindulys avatar jindulys commented on August 28, 2024

What is the view you get inside your sizeProvider?

let view = provider1.view(at: index)

Could you check its class?

If it is a GenericSingleLineInputView, could you check its title and subtitle's content?

Usually for sizeProvider, you'd better calculate size based on data instead of using view to do that.

from collectionkit.

bernhardwaidacher avatar bernhardwaidacher commented on August 28, 2024

Usually for sizeProvider, you'd better calculate size based on data instead of using view to do that.

Thanks for that info. I have planned to do this, but thought maybe there is another way to solve this issue. Thank you!

from collectionkit.

pteasima avatar pteasima commented on August 28, 2024

@bernhardwaidacher would you mind reopening the issue so that we can get a reaction? I dont wanna start a new issue since it follows the discussion here.

from collectionkit.

pteasima avatar pteasima commented on August 28, 2024

@lkzhao Thanks for the reply. I agree that autolayout is slow but I dont quite get the "thousands of views" point. My sample code above seems to work even for large numbers of elements.

Is there a situation where CollectionKit asks for a size but the view hasnt been created and thus cannot be used for calculating size? This would make by solution from above impossible. I still have some ideas how to handle this but it would likely require bigger changes (and I would likely give up:))

from collectionkit.

pteasima avatar pteasima commented on August 28, 2024

scratch that. I digged into the source and now I get your point. My confussion was that I didnt realize that provider.view(at:) actually constructs the view, I thought it will have been constructed and this is only a getter. Thanks for your time.

from collectionkit.

pteasima avatar pteasima commented on August 28, 2024

@bernhardwaidacher with this new information, I discourage using my sample code from above. It really does create all views eagerly and the performance will be terrible.

from collectionkit.

lkzhao avatar lkzhao commented on August 28, 2024

@pteasima
Try this maybe.

class ViewController: UIViewController {
  let collectionView = CollectionView()
  override func viewDidLoad() {
    super.viewDidLoad()
    let dummyCell = YourView()
    let viewUpdater = { (view: YourView, data: Int, index: Int) in
      view.backgroundColor = .red
      //...
    }
    collectionView.provider = CollectionProvider(
      data: [1],
      viewUpdater: viewUpdater,
      sizeProvider: { (index, data, maxSize) -> CGSize in
        viewUpdater(dummyCell, data, index) // first update the cell with current index's data
        return dummyCell.systemLayoutSizeFitting(maxSize)
      })
  }
}

keep in mind that performance of this won't be great for a lot of cells.

There is also the ViewCollectionProvider class which is a special CollectionProvider that allows you to use existing views if you have them constructed already.

from collectionkit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.