kishikawakatsumi / ibpcollectionviewcompositionallayout Goto Github PK
View Code? Open in Web Editor NEWBackport of UICollectionViewCompositionalLayout to earlier iOS 12
License: MIT License
Backport of UICollectionViewCompositionalLayout to earlier iOS 12
License: MIT License
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 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.
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 !
I want to use a new version (v0.6.8) because this PR (#124) is not reflected.
Thanks to great OSS!
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;
}
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!
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.
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 :)
Hello @kishikawakatsumi,
I couldn't figure out what the problem is but facebook/facebook-ios-sdk#1187 is the same issue that your framework got.
No other spm compatible framework which I use has the problem. Linking the binary to the ui test target doesn't fix the problem.
Do you have an idea what to look for? Your other framework https://github.com/kishikawakatsumi/KeychainAccess works perfectly.
Regards
Andi
How to generic dataSource, for example:
my homepage have many section with many data type model.
var dataSource: UICollectionViewDiffableDataSource<Section, T>! = nil
*** 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}'
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?
Any UICollectionLayoutSectionOrthogonalScrollingBehavior except .none cause crash on iOS 11 if a cell need to be reloaded (i.e. title of cell was changed).
"*** -[__NSDictionaryM setObject:forKey:]: key cannot be nil"
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).
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!
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)
}
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)
}
}
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.
// 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
}
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?
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))
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
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
There is a regression from 3-4 days ago.
As far as I can tell, top
and leading
are handled here but there's no corresponding trailing
/bottom
on the other side.
I tried quickly to track it down, but nothing was obvious to me.
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.
I found LayoutGroup.contentInsets extended whole content width.
reproduction code is here https://github.com/ichiko/IBPCVCLLayoutGroupContentInsetsBug.
When horizontal column >= 2, collectionView width was larger than window width witch scrollable horizontal.
expected (run on iOS 13) | actual (iOS 12.4) |
---|---|
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.
setCollectionViewLayout
in viewDidAppear
in the collection view controller.viewDidAppear
gets called again. You can do this a few times.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)
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!
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.
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
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.
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)
over 13.0, it will generate UICollectionViewCompositionalLayout
for the super class
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.