Summary:
## Changes in this pull request
It's been a few years since I did an audit of our test suite. The majority of changes to IGListKit since then were adding additional error checking and hardening, so this was relatively straightforward.
### Checklist
- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/main/.github/CONTRIBUTING.md)
Pull Request resolved: https://github.com/instagram/IGListKit/pull/1654
Reviewed By: jurmarcus
Differential Revision: D91551666
Pulled By: TimOliver
fbshipit-source-id: c89c7a45abebb44dbf50b252bfadc9a7c2928683
Summary:
## Changes in this pull request
`FBReportMustFix` isn't recognized by the public version of IGListKit. It is wrapped by `IGFailAssert` to abstract error tracking between the public and private versions, and so this change was causing the GitHub repo to stop compiling.
This diff makes the appropriate change and confirms the unit tests are passing again.
### Checklist
- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/main/.github/CONTRIBUTING.md)
Pull Request resolved: https://github.com/instagram/IGListKit/pull/1653
Test Plan:
Compiling again!
{F1984942550}
Differential Revision: D91551520
Pulled By: TimOliver
fbshipit-source-id: bdc9f786092853252011c551ce6d214a01445c63
Summary:
Add a defensive check in `IGListCollectionViewLayout` to prevent `NSInternalInconsistencyException` crashes caused by NaN frame values.
**Problem:**
When UIKit attempts to use these NaN frames, it throws `NSInternalInconsistencyException` because NaN comparisons always return false, breaking layout calculations.
**Solution:**
- Check for NaN values in the frame before setting it on `UICollectionViewLayoutAttributes`
- Log a warning via `FBReportWarning` for visibility and debugging
- Return `nil` (consistent with existing OOB check pattern) to prevent the crash
Reviewed By: dinhvh
Differential Revision: D91268614
fbshipit-source-id: 092d85c4b9ef9d5a84238ab4bc4b21a3d768a928
Summary:
These asserts could be very helpful to debug tricky crashes, but they don't tell us enough about which object/section-controller are returning invalid data. The backtrace itself doesn't have the info.
Lets:
* Add object and section-controller class names, but don't include the entire object description (can be very long)
* Clean up how we print NSIndexPath without the memory address. This can make group-by a lot more useful.
## Examples
Before:
> IGListAdapter returned NaN height = nan for item at indexPath <<NSIndexPath: 0x90c0bb66134b9c8a> {length = 2, path = 0 - 0}>
After:
> IGListAdapter returned NaN width = nan {indexPath: 0-0, object: IGFooViewerLoadingModel, sectionController:IGFooLoadingSectionController, dataSource: IGFooDataSource}
Before:
> Section controller nil for section 1
After:
> Section controller is nil {indexPath: 1-0, object: IGStoryFooViewModel, sectionController: nil, dataSource: IGFooDataSource}
Differential Revision: D90555737
fbshipit-source-id: 7a993ce667d894fa98d59f2258158bf78e3fa33f
Summary:
Today, the IGListAdapterDelegateAnnouncer is different than most other announcers in IG/FB/etc in that it not thread safe to add and remove listeners.
However, this isn't really enforced, and has lead to people calling add / remove on background threads, which is creating crashes: https://fburl.com/logview/f1x4ytdl
A different way to deal with this problem is to make the IGListAdapterDelegateAnnouncer thread safe (eg D87806041), but the principle there seems to be that this class is only intended to be dealt with on the main threasd.
So, the fix here is to just make sure we call this on the thread and add asserts. using on_main here guarantees that we don't dispatch if we are already on the main thread, so it should be safe to add.
Reviewed By: manicakes
Differential Revision: D88427711
fbshipit-source-id: 41f352495e0238618e4d6efe938bdaed370bb139
Summary:
Another code automation changed the import stylings in some of the IGListKit headers. We've since updated the automation to skip IGListKit in future, so we just need to revert this commit and we should be good to go again!
Pull Request resolved: https://github.com/instagram/IGListKit/pull/1647
Test Plan: As long as the tests pass both internally and externally.
Reviewed By: jurmarcus
Differential Revision: D87851377
Pulled By: TimOliver
fbshipit-source-id: e6f1f98684457be41d9a7e197fb44dc8077bc8f0
Summary:
## Initial Devmate Prompt:
[https://www.internalfb.com/logview/basel\_ios\_crashes/cdf37c300a6041eebafd4aa2c2ed9846](https://www.internalfb.com/logview/basel_ios_crashes/cdf37c300a6041eebafd4aa2c2ed9846)
What's the issue that's causing this FAD?
Can you create a fix for it?
---
## LLM-generated Summary:
The changes fix a crash in IGListSectionMap.m that occurs during IGListAdapter deallocation. The issue is caused by accessing a nil or invalid sectionController, which is resolved by adding a nil check before invoking the block. This fix prevents the crash when section controllers are no longer available in the map during cleanup, ensuring a safe and defensive programming approach to handle the race condition during deallocation.
---
Session: DEV17393008
Differential Revision: D87261228
fbshipit-source-id: 8c147909b3090d8cf2914da1957bcd5d5b8b2cb4
Summary:
It looks like D86316341 caused the GitHub unit tests to stop passing since SPM relies on IGListKit and IGListDiffKit being in the same directory so there are no module imports.
This diff adds the same `__has_include` conditional checking so our internal and external module configurations will both work.
Pull Request resolved: https://github.com/instagram/IGListKit/pull/1644
Test Plan:
The external tests are working again. As long as the internal tests also pass, we should be good!
{F1983488354}
Reviewed By: m3rlin45
Differential Revision: D86943807
Pulled By: TimOliver
fbshipit-source-id: c741acbb1f8425e92834daec720d4be3b3c264da
Summary: Replace unprefixed includes in exported_headers with their prefixed equivalents. This avoids filesystem walking to find headers and makes it possible to resolve the headers via header maps.
Reviewed By: d16r
Differential Revision: D86316341
fbshipit-source-id: c3f5d4c5a8911cec45ccac2acd5ea466c244055e
Summary: Updates the CHANGELOG with all of the latest enhancements and fixes, and bumps the version number of IGListKit to 5.1.0
Reviewed By: benhgreen
Differential Revision: D85926201
fbshipit-source-id: c3c37bbfb859da3ef753b3a8074cf28c8b0febfa
Summary:
## Changes in this pull request
Issue fixed: Provided support for Context Menus
### Checklist
- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)
Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1430
Test Plan: https://pxl.cl/2F940
Reviewed By: benhgreen
Differential Revision: D45309023
Pulled By: TimOliver
fbshipit-source-id: 9f3d7871288437414ae3c0d2941802aa506a5553
Summary:
I noticed that in the latest commit to main, [the build had started failing](https://github.com/Instagram/IGListKit/actions/runs/18856759807/job/53806413365).
Looking into it, it seems GitHub has removed `iOS 26.0` as a valid destination, replacing it with both `iOS 26.0.1` and `iOS 26.1` on their `macos-26` runner target.
I tried removing the explicit iOS version define in the CI YAML file, but unfortunately, this ended up breaking the UI test target. It turns out that one requires the 'preboot' step in order to work, and without an OS number, the preboot, and xcodebuild steps both arbitrarily choose different simulator slices to execute. :(
On top of that, when I fixed this issue and tried to do a fresh build, `IGSectionMap` was throwing a build error in one of the IGAsserts, requiring that the provided `NSUInteger` needed to be typecast to `(unsigned int)`.
So, in order to fix this moving forward, I went back to macos-14, since we're pretty safe in that iOS 18's build numbers probably won't be updated in that one for a fair while.
Pull Request resolved: https://github.com/instagram/IGListKit/pull/1643
Test Plan: I confirmed the external tests pass, so as long as the internal ones pass too, we should be good!
Reviewed By: m3rlin45
Differential Revision: D85658369
Pulled By: TimOliver
fbshipit-source-id: 78cc0f9d9e9e095bb99c010d844d2186be0017f6
Summary:
`diffIdentifier` should not have changed before an update starts, otherwise we can't look up the corresponding section-controller.
Lets add an assert when we detect this issue. In a few months, we should evaluate if this is still useful.
Differential Revision: D85456085
fbshipit-source-id: 9aee649477618e2fdcd5b8e972d8eae0719bed85
Summary: Objects in `IGListSectionMap` should be `id<IGListDiffable>`. This is gonna make the next diff easier too. We probably should do the same with `IGListAdapter`, but that requires a bigger refactor for another time.
Differential Revision: D85372926
fbshipit-source-id: 0b9828ce28bd7906a6abf13d6bb3cc2a9fbb2e9c
Summary: One of the implementation files in IGListKit didn't have the appropriate copyright headers, which was causing one of the open source health checks to throw a warning.
Reviewed By: DimaVartanian
Differential Revision: D83947233
fbshipit-source-id: c5ce059373a57b4b235810f42e21bb4ab5181051
Summary:
## Stack
We aim to remove +load methods from the codebase to reduce pre-main startup time and to unblock enabling startup optimizations
## Diff
UICollectionViewLayout+InteractiveReordering marked as Internal in IGListKit. I am assuming that this is an internal implementation detail of the IGListKit and is not supposed to run globally outside of the IGListKit context. Based on that assumption I migrated global +load API to a `setup` method, which is being execution in IGListAdapter constructor, core class of the IGListKit library
Reviewed By: AfrazCodes
Differential Revision: D81592721
fbshipit-source-id: 718b936e669669c66ec5b6c80fefc4bd106170c2
Summary: We're finding ourselves with the need to delesect a lot of cells, but still allow selction. We could do it in each section-controller, but it's easy to mess up and forget in new section-controllers. So, lets add "auto deselection" to `IGListAdapter` directly. When enabled, section-controllers still get the `-didSelect`, but they don't need to deselect the cell.
Differential Revision: D80272474
fbshipit-source-id: 3d905f1f37def6af3cbc6f4d35e256826b7555fb
Summary:
### Context
This stack implements base `UIKit` types in Objective-C by removing the requirement to provide `NSCoder` based constructor in Swift.
### This diff
`IGListKit` seems to have `NSCoder` constructors marked unavailable except for the single type `IGListCollectionViewLayout`. So adding it there.
### Project context / references
[Opti project](https://fburl.com/gdoc/7hekhwd5)
[META UIKit RFC](https://fburl.com/gdoc/9maag852)
Reviewed By: TimOliver
Differential Revision: D77116862
fbshipit-source-id: 9ae48258131a439b1e8ae84ac23ff5ea14b87281
Summary: Many protocols that are conformed only by VCs needed to be marked main actor.
Reviewed By: ebgraham
Differential Revision: D74761535
fbshipit-source-id: b5d047b625df5cf16759aa5c19e5bf57594a3d99
Summary: The default implementation of `-[UICollectionView preferredFocusedView]` can create/dequeue off-screen cells, which causes perf issues and bugs. Lets create `IGListExperimentFixPreferredFocusedView` to return a visbile index-path.
Differential Revision: D74484148
fbshipit-source-id: f710be56b938f8474278cf88b7e2e4268f702f1d
Summary:
Easy little diffs to correct the spelling heathens of the past. O:)
As titled.
Differential Revision: D73490845
fbshipit-source-id: f8868eb5a1ebaac771e73d832baa1245a9cd2c5a
Summary:
## CONTEXT
`IGListAdapterDelegate` currently has methods that are fired when an object is *first* displayed and when an object *ended* display on screen. For many use cases this works but there are use cases in which it would be helpful to know whenever a cell will be displayed or ends display. This is especially relevant in the `IGListAdapterDelegateAnnouncer` which will enable you to add code for tracking cells globally. This change also balances the `IGListAdapterDelegate` with `IGListDisplayDelegate` which has methods which include the cell as well
## PLAN
This diff will be go out in multiple parts
- delegate method addition (many file change due to our pattern of not preferring default implementation of protocol methods)
- Update to `IGListDisplayHandler` and `IGListAdapterDelegateAnnouncer` for invocation of delegate methods
- Unit test additions
## THIS DIFF
This diff changes adds the invocation of `IGListAdapterDelegate` in `IGListDisplayHandler` and `IGListAdapterDelegateAnnouncer`. The cell lifecycle method will be called every time. cell will display and did end display as opposed to the existing methods which are only called the *first* and *last* time an object is displayed
Differential Revision: D70348078
fbshipit-source-id: 820cd22af217f01f2d4916a70e203d9afc4c6a6d
Summary:
## CONTEXT
`IGListAdapterDelegate` currently has methods that are fired when an object is *first* displayed and when an object *ended* display on screen. For many use cases this works but there are use cases in which it would be helpful to know whenever a cell will be displayed or ends display. This is especially relevant in the `IGListAdapterDelegateAnnouncer` which will enable you to add code for tracking cells globally. This change also balances the `IGListAdapterDelegate` with `IGListDisplayDelegate` which has methods which include the cell as well
## PLAN
This diff will be go out in multiple parts
- delegate method addition (many file change due to our pattern of not preferring default implementation of protocol methods)
- Update to `IGListDisplayHandler` and `IGListAdapterDelegateAnnouncer` for invocation of delegate methods
- Unit test additions
## THIS DIFF
This diff changes the delegate to include the methods that pass in the cell. This is a huge many file diff because we prefer to not include default implementations of protocol methods. This makes the delegate change a breaking change.
Reviewed By: maxolls
Differential Revision: D70348102
fbshipit-source-id: 40709ba8a9112d8855d5ce5ecfd5930b5c79bf26
Summary:
The GitHub CI seems to be failing still since we added some new header files and didn't include the necessary ones in the IGListKit.h umbrella header.
This PR:
* Updates the umbrella header to include the new header files
* Updates the visibility of the private headers so they don't need to be included in the umbrella.
* Does a general clean-up of the Xcode project, re-ordering all of the newly imported files.
Assuming this all passes the external CI, we can land it in Phabricator.
Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1622
Test Plan: GitHub CI has passed: https://github.com/Instagram/IGListKit/actions/runs/13851019458
Reviewed By: fabiomassimo
Differential Revision: D71178515
Pulled By: TimOliver
fbshipit-source-id: 1ea643a7bc7a401c45af2776c2a66e3b806035d7
Summary:
## Changes in this pull request
Issue fixed: [1620](https://github.com/Instagram/IGListKit/issues/1620)
### Checklist
- [ ] All tests pass. Demo project builds and runs.
- [ ] I added tests, an experiment, or detailed why my change isn't tested.
- [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [ ] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/main/.github/CONTRIBUTING.md)
Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1621
Test Plan:
Tested that IG builds with these changes without issue. All seems good.
As
Reviewed By: NSProgrammer
Differential Revision: D70959852
Pulled By: TimOliver
fbshipit-source-id: 087411463ad1b7c0698d7aba543d85c9013abf39
Summary:
It's inefficient to get the unordered array of visibleObjects to then try to find the order of those objects after. Instead, introduce a new `indexesOfVisibleObjects` API to `IGListAdapter` which will inherently preserve order.
Will use this to help find the previous and next "item" to scroll to with Main Feed.
Differential Revision: D70835725
fbshipit-source-id: a5f66681e0184299d92f220be194b5554639a7da
Summary: We'd like to know which `IGListAdapter` is associated with a `UIViewController`, so lets keep track of that. Every adapter should have only 1 controller and it can't change.
Differential Revision: D70631091
fbshipit-source-id: 7f818d7e8f1858a4c80e223be6d5aad5cfc639cf
Summary: Adding more debug info to figure out what's happening in sundial.
Differential Revision: D70545124
fbshipit-source-id: f0ce51529a712328941b9f9b08b70894388bdb14
Summary:
## Context
UICollectionViews are allowed to return nil attribute values; it is not a programmer error and in some cases it can be used as a feature. `IGListCollectionViewLayout` doesn't consider this; if subclasses return nil attributes then a crash will occur.
## This Diff
Let's apply a check to ensure the attribtues are non-nil before adding to the result array.
Differential Revision: D70492114
fbshipit-source-id: b7203ded2928d2892693f95bb56b45f03c2530a2
Summary:
## Context
`IGListCollectionViewLayout` users may have need to know more about the invalidation contexts it uses -- either to supply accurate invalidation contexts, or to understand more about invalidations (example -- usages of preferred layout attributes).
## This Diff
Exposes `IGListCollectionViewLayoutInvalidationContext` publicly, and renames properties to something a little nicer.
Differential Revision: D69679455
fbshipit-source-id: 2bd3e414ea1f48522546854d0287f3ca9d873ec6
Summary: Add more metadata when we return nil cells in IGListKit.
Differential Revision: D69577117
fbshipit-source-id: 0834857eb429154f35bacf7e00d347ce99d28ee6
Summary: When the value is nil, it will result in a crash on iOS 18.
Differential Revision: D69565468
fbshipit-source-id: 5936ec253cd1e0dfb8b494ebb1364c6a14e79170
Summary: We were not passing the right coordinates when finding the indexPath of the cell we are hovering over causing all sort of havoc
Differential Revision: D69207295
fbshipit-source-id: 9b2df93ae00eceb85fde86f766a3b225fc8c56f9
Summary: This allows to get `layoutAttributesForItemAtIndex` for a given cell via list kit, not directly via UICollectionView → layout → …
Reviewed By: avielg
Differential Revision: D68189875
fbshipit-source-id: 9f81143d1a78ade6b9c14b3c012f22f222ded5b2
Summary: This was a killswitch to be safe, so lets clean it up.
Differential Revision: D67072925
fbshipit-source-id: ac54972030e7d53e7abd95025e45773aa3c5efc6
Summary:
Threads has now run into multiple instances of device-only crashes resulting from usage of automatically converted Swift async versions of `performUpdates(animated:)` and `reloadData()`.
See D64428846, D64876801.
The crashes appear to stem from the opaque, automatically generated async methodology:
```
objc completion handler block implementation for escaping callee_unowned convention(block) (unowned Bool) -> () with result type Bool
```
Our `IGListKit` infra assuming ownership of these `callee_unowned` blocks seems to be problematic: the block can be released/nil'd, and our downstream [`[-[IGListReloadTransaction _executeCompletionBlocks:]`](https://www.internalfb.com/intern/logview/redirect/?filename=IGListReloadTransaction.m&line=82&repo=fbsource&revision=c1e4b4a34ff90e4785983b260f10543af6536215&build=655525612) execution then crashes.
Given this incompatibility with automatic conversion, here I propose:
1. marking the relevant `IGListAdapter.h` APIs with `NS_SWIFT_DISABLE_ASYNC`
2. providing manual async APIs in a new `IGListAdapter+Async.swift` extension hosted in `IGListSwiftKit` that existing callers can now make use of.
Differential Revision: D64881920
fbshipit-source-id: b15a5141a79491c1871b92f4f84a0c29b6045ee0
Summary:
In a few cases, we need to listen to all `IGListAdapter` events. We bend over backwards to detect adapters and swap their delegate with a proxy objects. Lets make things simpler and build it right into `IGListKit` by allowing global announcers, starting with `IGListAdapterDelegate`, but we could expand to the others if we like this.
Generally, we want to avoid anything global, but given the complexity of the alternative, this feels like the better tradeoff.
Differential Revision: D64042609
fbshipit-source-id: 0ca6bada27e640fee5a231148427be41994e4d43
Summary:
iOS 18 has new exceptions, which can be a bit tough to debug. The common ones we see:
1. Cell dequeue outside of -cellForIndex
2. Dequeue being called more than once
3. Returning a cell that was not dequeued
Lets add an assert for each. #1 and #2 can actually assert on the problematic call, which will give a nice stack strace. #3 will still have a generic stack trace, but at least we'll see the section-controller.
Differential Revision: D62809660
fbshipit-source-id: 454c44598d4b21e09e6f66eb63c502b1b966a993