Giter Site home page Giter Site logo

kishikawakatsumi / ibpcollectionviewcompositionallayout Goto Github PK

View Code? Open in Web Editor NEW
1.5K 29.0 144.0 11.01 MB

Backport of UICollectionViewCompositionalLayout to earlier iOS 12

License: MIT License

Objective-C 41.34% Swift 58.38% Ruby 0.29%
uicollectionviewlayout compositional-layouts uikit backport

ibpcollectionviewcompositionallayout's Issues

SupplementaryItem does not anchor correctly on items with estimatedHeight

I've found that when trying to add a separator as a supplementary item it doesn't update it's position from the original estimated size. If I specify an estimated height of an item as 200 and then the cell lays out as 150 the supplementary item is still anchored to 200. Works fine on iOS13, just breaks on older versions of the OS.

Below is the layout I am using:

let separatorAnchor = NSCollectionLayoutAnchor(edges: .bottom, absoluteOffset: CGPoint(x: 0, y: 1))
let separatorSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(1))
let separator = NSCollectionLayoutSupplementaryItem(layoutSize: separatorSize, elementKind: SeparatorSupplementaryView.kind, containerAnchor: separatorAnchor)

let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(201))
let item = NSCollectionLayoutItem(layoutSize: itemSize, supplementaryItems: [separator])

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])

let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)

let layout = UICollectionViewCompositionalLayout(section: section)

[Crash]Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForDecorationViewOfKindOfKind:

Crash Message:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForDecorationViewOfKindOfKind: CustomView at path <NSIndexPath: 0xc3c93bf6eb9e0b17> {length = 2, path = 3 - 0}'
terminating with uncaught exception of type NSException

How to fix this crash?
Thanks for help.

interItemSpacing issue for nested group

when i setted interItemSpacing for a vertical group which cotnains two or more horizontal groups, the interItemSpacing for the vertical group is ignored if run on iOS 12 or earlier, but it behaviors fine on iOS 13 or later.To reproduce this issue, just replace the function createLayout of TwoColumnViewController with codes below:

`
func createLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                          heightDimension: .absolute(44))
    let group1 = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 2)
    group1.interItemSpacing = .fixed(10)
    let group2 = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 2)
    group2.interItemSpacing = .fixed(10)
    let group = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44+10+44)), subitems: [group1, group2])
    let spacing = CGFloat(10)
    group.interItemSpacing = .fixed(spacing)

    let section = NSCollectionLayoutSection(group: group)
    section.interGroupSpacing = 20
    section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10)

    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
}

`
Hope you can reply me !

Release v0.6.8

I want to use a new version (v0.6.8) because this PR (#124) is not reflected.
Thanks to great OSS!

IBPCollectionCompositionalLayoutSolverResult is empty and crashed

uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

- (IBPNSCollectionLayoutItem *)layoutItemAtIndexPath:(NSIndexPath *)indexPath {
    NSArray<IBPCollectionCompositionalLayoutSolverResult *> *results = self.results;
    IBPCollectionCompositionalLayoutSolverResult *result = [results objectAtIndex:indexPath.item % results.count];
    return result.layoutItem;
}

Supplementary view offsetting is ignored

It is possible on iOS 13 to offset a supplementary view.
It took me a while to understand how they work and to obtain the result I wanted.

Unfortunately the library didn't support the offsets.
I have written the code needed to make my views work (top and bottom).
I also spent some time trying to modify the sample code of HeaderFooterViewController.swift to try several alternative configuration and I'm confident it's very close to what iOS 13 is doing in most situations.

PR is following this issue.

Thanks!

Decoration views not being offset by supplementary views

This might be a little hard to follow, but refer to the image below.

A section is configured with a NSCollectionLayoutDecorationItem.background(elementKind:) (the grey background), and it also has a boundarySupplementaryItem (the header that says "Kategorien"). No content insets, nothing fancy.

The cell itself ("Information zu Krebs") matches the height of the decoration item (✅), but the y-position is aligned with the header, not the cell.

image

This regression was introduced a couple of days ago when adding support for pinned headers, I think.

I'll try to track it down in the meantime, but you might know the solution more quickly :)

Generic dataSource.

How to generic dataSource, for example:
my homepage have many section with many data type model.
var dataSource: UICollectionViewDiffableDataSource<Section, T>! = nil

Crash on below iOS 13 devices. *** Assertion failure in -[UICollectionViewData layoutAttributesForDecorationViewOfKind:atIndexPath:]

*** Assertion failure in -[UICollectionViewData layoutAttributesForDecorationViewOfKind:atIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore/UIKit-3698.140/UICollectionViewData.m:1078
2020-02-20 20:39:44.141884+0530 latte[506:67064] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForDecorationViewOfKindOfKind: section-background-element-kind at path <NSIndexPath: 0xa82b494003cee6b8> {length = 2, path = 3 - 0}'

Floating Point issues

Whew, this one was a tricky one, and probably a bigger issue to address (there are a lot of float comparisons!), so I'm interested in your thoughts.

The comparison here was causing a layout issue for me, where an orthogonal view wasn't moving down below the header (boundary supplementary) view.

I was getting these values:

(lldb) p itemFrame
(CGRect) $6 = (origin = (x = 0, y = 314.66666666666669), size = (width = 414, height = 58))
(lldb) p frame 
(CGRect) $7 = (origin = (x = 0, y = 314.66666666666663), size = (width = 414, height = 256.66666666666669))

Obviously in UI coordinates, 314.66666666666669 is the same as 314.66666666666663, but the comparison failed.

How do you think we should handle comparisons like this across the lib?

Problem with reusing cells inside nested collection views. (orthogonal scrolling)

Hi 👋

when orthogonal scrolling is enabled, cells are being dequeued from the root collection view and placed in a nested collection view to achieve the orthogonal scrolling which is pretty nice.

the problem is the root collection view cannot reuse those cells anymore,, which is leading to creating unlimited number of cells when scrolling horizontally (orthogonally).

Fatal error when passing data between view controllers using prepare for segue

I tried this framework.
Everything works except when I need to pass data from the collection view to another view controller, it gave me fatal error. This error only occurs on devices running below iOS 13.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ShowPaintingList" {
            guard let indexPath = categoryCollectionView.indexPathsForSelectedItems?.first
                else { fatalError() } // fatal error here
            
            if let paintingListCollectionViewController = segue.destination as? PaintingListCollectionViewController {
                paintingListCollectionViewController.allPaintings = genreSectionData[indexPath.item]
            }
        }
    }

Xcode console does not output any error message so this is kinda difficult to debug.
So I commented out guard let and else { fatalError() }, change indexPath to indexPath!. Now Xcode says indexPath is nil.

I am not sure passing data is supported by this framework, but what is the point of using collection view if it cannot pass data...If anyone had any success please let me know, thanks!

Crash for recursive call on `setCollectionViewLayout(_:animated:)`

I have a feature to switch layout ( grid <-> list), so I call setCollectionViewLayout to switch.
But if I start from 'grid -> list -> grid', it will crash.
From the call stack, we can see two IBPUICollectionViewCompositionalLayout is called repeatedly.

p.s. in iOS version below iOS 13.

Example code as follow,

    switch layoutMode {
    case .grid:
      collectionView.setCollectionViewLayout(grid, animated: false)
    case .list:
      collectionView.setCollectionViewLayout(list, animated: false)
    }

call stack & error message as follow,
截圖 2019-12-03 下午3 29 34

[Crash] Thread 1: EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)

Hello there! I have a section:

final class SomeSection: NSCollectionLayoutSection {
    
    convenience init() {
        let estimatedWidth: CGFloat = 100
        let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(estimatedWidth),
                                              heightDimension: .absolute(30))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: nil,
                                                         top: nil,
                                                         trailing: .fixed(8),
                                                         bottom: nil)
        let groupSize = NSCollectionLayoutSize(widthDimension: .estimated(estimatedWidth),
                                               heightDimension: .absolute(30))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
                                                       subitems: [item])
                
        self.init(group: group)
        
        orthogonalScrollingBehavior = .continuous
        
        interGroupSpacing = 8
        
        contentInsets = NSDirectionalEdgeInsets(top: 12,
                                                leading: 16,
                                                bottom: 0,
                                                trailing: 0)
    }
}

And I got crash on iOS < 13:
Снимок экрана 2022-04-29 в 10 06 48

Dear, please help me: I probably found a big bug, in iOS 10.3, update datasource with UICollectionViewCompositionalLayout will not work correctly, please look at below.

Dear Kishikawa Katsumi:

I use IBPCollectionViewCompositionalLayout  in iOS 13 will no problem, but in iOS 10 is not ok, please see the screenshot and the IBPCollectionViewCompositionalLayout.zip example that I sent to you below,  run and select OrthogonalScrollBehaviorViewController.swift with iOS 10.3, the Xcode will crash.

Why it is, please help me, I take two days to debug this question, but no answer.

Because your email can’t receive more than 10MB demo.zip file. So I put the demo.zip project on the Aliyun OSS, sincerely hope you can download the demo project and debug it.

Please download the demo:  https://dxy-demo.oss-ap-northeast-1.aliyuncs.com/IBPCollectionViewCompositionalLayout.zip

Or the link of github: https://github.com/willokyes/IBPCollectionViewCompositionalLayout-Demo

I'm looking forward to your reply.

Thank you.

IBP-run-iOS10-crash

the below code of layout section before iOS 13 is not work correctly

     // i.e.  all iOS version is work correctly
    func layoutSection(layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                              heightDimension: .fractionalHeight(1.0))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(185),
                                               heightDimension: .absolute(160))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        
        let section = NSCollectionLayoutSection(group: group)
        section.contentInsets = .init(top: 0, leading: 15, bottom: 0, trailing: 15)
        section.orthogonalScrollingBehavior = .continuous
        section.interGroupSpacing = 10
        return section
    }
    
    // i.e.  before iOS 13 is not work correctly
    func layoutSection_v1(layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? {
        let itemCount = items.count
        guard itemCount > 0 else {
            return nil
        }
        
        let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(185),
                                              heightDimension: .fractionalHeight(1.0))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        let width = CGFloat(15 + 185 * itemCount + 10 * (itemCount - 1) + 15)
        let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(width),
                                               heightDimension: .absolute(160))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        group.contentInsets = .init(top: 0, leading: 15, bottom: 0, trailing: 15)
        group.interItemSpacing = .fixed(10)
        
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .continuous
        section.interGroupSpacing = 0
        return section
    }

About iOS minimum deployment target version

I built IBPCollectionViewCompositionalLayout target with 8.0 deployment target and no errors happened. So can we decrease the minimum deployment target to 8.0 so that more products can adopt this awesome library? Or maybe I missing some considerations for the current 10.0 deployment target version?

Performance issue during scroll / always create new cell instances

Hi,
i have performance issues with the IBPUICollectionViewCompositionalLayout.

During the scroll, the IBPUICollectionViewCompositionalLayout's layoutAttributesForElementsInRect method always ask data source for the cell, if we use estimated item size and item contentInsets.

the documentation / comments says:
contentInsets are ignored for any axis with an .estimated dimension
which is not ignored, makes the performance really bad.

Even if the collectionView's dequeueReusableCell method are used, it creates a new instance of the cell (and run the layouting)

Issue is on iOS 12, there is no any unwanted cell creation or performance issue on iOS 13

how to reproduce:
use estimated item height in Examples/ListViewController2:
change:
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
to:
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(10.0))

Crashing for below layout configuration

    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                          heightDimension: .estimated(100))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .fixed(8),
                                                     top: .fixed(8),
                                                     trailing: .fixed(8),
                                                     bottom: .fixed(8))
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                           heightDimension: .estimated(100))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
                                                   subitems: [item])

    let section = NSCollectionLayoutSection(group: group)
    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout

Hello Team,
Thank you for this library, I have been playing with estimate dimension and when i try to set the below code

       item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .fixed(8),
                                                         top: .fixed(8),
                                                         trailing: .fixed(8),
                                                         bottom: .fixed(8)) 

it crashes at this line

Screenshot 2019-09-26 at 12 16 43 PM

Estimated values are used instead of the calculated values

IBPUICollectionViewCompositionalLayout's prepareLayout method uses the estimated values for calculate the contentFrame, which leads to wrong content size, wrong origins for sections (if we have multiple sections).

This issue and #114 are related.
We have problem in all layouting, not only orthogonal sections.
The issue exists even if the estimated value are greater or less than the actual size

iOS13 vs iOS12

Reload 2 items toggle state in same section causing the whole section to reload( below iOS 13 )

Reloading "state only values of specific items in horizontal section" is causing the section to scrollto first (it's reloading whole section)

        ///on cell did select
        guard var currentSnapshot = dataSource?.snapshot() else { return }
        var itemsToReload:[SomeClassTypeHashable] = []
        //toggle state of  current cell
        let selectedItem = currentSnapshot.sectionIdentifiers[indexPath.section].items[indexPath.item]
        if var item = selectedItem as? Playable{
            item.isPlaying = !item.isPlaying
            itemsToReload.append(selectedItem)
        }
        //reset state of all other cells as playing capabilities will only be available at one cell at a time.
        currentSnapshot.sectionIdentifiers[indexPath.section].items.filter({(($0 as? Playable)?.isPlaying ?? false) == true && $0 != selectedItem}).forEach({
            var prevItem = ($0 as! Playable)
            prevItem.isPlaying = false
            itemsToReload.append(castedPrevItem as! SomeClassTypeHashable)
        })
        
        currentSnapshot.reloadItems(itemsToReload)
        
        dataSource?.apply(currentSnapshot)

Works perfectly in iOS 13 but scrolling issues are prominent in below versions of iOS 13.

Not clearing nested collection views on `setCollectionViewLayout(_:animated:)`

Whenever you call collectionView.setCollectionViewLayout(layout, animated: false) with a layout that contains a horizontal scrolling section, a new collection view gets added for the horizontal scrolling section, but older collection views are not removed.

This results in "ghost" views being displayed in the view.

Quick way to replicate

  • Create a navigation controller that navigates to a collection view controller.
  • Call setCollectionViewLayout in viewDidAppear in the collection view controller.
  • Initiate interactive dismiss gesture but cancel halfway so that viewDidAppear gets called again. You can do this a few times.
  • Check debug view hierarchy to see leftover collection views.

LayoutGroup ContentInsets are not honored

I've found that the LayoutGroup.contentInsets are not being honored.

Below is a sample layout that does not get the padding applied:

let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(201))
let item = NSCollectionLayoutItem(layoutSize: itemSize)

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
group.contentInsets = NSDirectionalEdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)

let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)

Decoration views are not registered in the orthogonal sections

Hello!
I've been working with the library.
First of all congratulations on the reimplementation, this is some very impressive work!

I just tried to implement a background decoration view on an orthogonal section.
Unfortunately this crashes the app as the embedded orthogonal collection view's layout seem to not receive the decoration views that are registered in the main layout.
I also faced the same situation trying to run the badge example in an orthogonal section.

I'll try to find a solution myself, but I'm not yet familiar enough with the library's source code to be confident I will succeed.

Thanks again!

[New Feature Request] Add New Feature in iOS 14

Support some thing like UICollectionViewCompositionalLayout.list and UICollectionLayoutListConfiguration

If you think this is necessary, I can list all new features and try to implement these.

Any update on this repository?

For now, 4 years later the time this repository makes a magic for early iOS 12 support, so many early iOS 12 devices still continue using by community.
It's neccessary to maintain, improve this repository. So I strongly hope the author continue considering support this repository.
Best regards!

visibleCells is empty in iOS 12

visibleCells is empty in iOS 12
I guess you didn't override visibleCells to cause this situation.
When used IBPCollectionViewCompositionalLayout in iOS12, it will create some IBUICollectionView as section to my collectionView, by this time the cell is not belong to my collectionView, but belong to IBUICollectionView.

Group. ContentInsets iOS12 in the bottom and the trailing cannot properly

Hello. By modifying demo, I found that error #100 still exists, and iOS 12 and 13 do not perform consistently. ContentInsets bottom and backward, uncontrollable, you can try running demos and modify the group.contentInsets of AdaptiveSectionsViewController in systems before iOS 13.

group.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 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.