- Fixed warning in Package.swift referencing a non-existent Resources directory.
- Fixed warning for a cross-module protocol conformance.
- Fixed deprecation warning by adopting
UIButton.Configurationfor swipe action buttons.
- The iOS 16.4 first responder workaround no longer checks UserDefaults, the workaround is always applied.
- Fixed an issue where animations would occur when dequeuing / reusing cells. A layout is now forced without animation before presentation.
- Fixed an issue where a full swipe of a swipe action could result in the cell being temporarily unresponsive.
- Fixed a crash that occurred when, while the cursor is on the first heading, we are on the Headings VoiceOver rotor and swipe up with one finger.
- Added support for
onDisplayandonEndDisplaycallbacks forHeaderFooters.
- CocoaPods has been removed and local development environment is now driven by Tuist.
- Changing a List's
identifiernow automatically resets the scroll position.
- Added a completion handler to ListView's
scrollTo(item:position:animated:completion:)andscrollToSection(with:sectionPosition:scrollPosition:animated:completion:)APIs.
- The
IOS16_4_First_Responder_Bug_CollectionViewworkaround is no longer capped to iOS versions less than 19.0. It was verified as required in the iOS 19 beta.
- Added the
ScrollCompletionHandlerViewControllerdemo to showcase the new completion handlers with different layout configurations.
- Blueprint dependency updated to 6.0.
- The
IOS16_4_First_Responder_Bug_CollectionViewworkaround has been capped to OS versions less than iOS 19.0 until the fix has been verified as required and functioning. - The interpretation of the
Listable.EnableIOS164FirstResponderWorkarounduser defaults flag now defaults totrueif no value has been set.
- Improving how
AutoScrollActionandVerticalLayoutGravity.bottomwork together by temporarily ignoring the bottom gravity logic while autoscrolling.
- Fixed an issue with
AutoScrollAction.OnInsertedItemandAutoScrollAction.Pinthat caused the scrolled offset to be reset to the bottom when usingVerticalLayoutGravity.bottom. - Fixed issue with the
didPerformclosures ofAutoScrollAction.OnInsertedItemandAutoScrollAction.Pin, where the visible items were stale after adjusting the offset with no animation.
- Adding new demos to showcase mixing
AutoScrollAction.OnInsertedItemandAutoScrollAction.PinwithVerticalLayoutGravity.bottom. - Adding a new
AutoScrollAction.Behaviorprotocol.
- Fixed a crash that would occur when a user would reorder / move items between sections.
PagedListLayoutnow supports a peek value, which allows items to peek into view from the leading/top and trailing/bottom edges.- Adding a
mostVisibleItemproperty toListScrollPositionInfo.
- Replacing the
isPagingEnabledboolean with aPageScrollingBehaviorenum. This gives layouts the ability to:- leverage
fullpage scrolling, where items are full width (equivalent toisPagingEnabledbeingtrue) - use
peekpage scrolling, where items can be less than the full width and peek into view (this is new functionality) - disable page scrolling via
none(equivalent toisPagingEnabledbeingfalse)
- leverage
ListScrollPositionInfo'svisibleItemsis now a set ofVisibleItemmodels, which contains apercentageVisibleproperty.
PagedListLayout.pagingBehavioris now configurable. This can be used to keep the items centered when peeking.
- Replacing
PagedAppearance.PagingSize.viewwith a.inset(Peek)case. This is used byPagedListLayoutto lay out items with an edge peek.
- Disabled cell content interaction when swipe actions were visible.
- Fixed a crash which could occur when a programmatic scroll down event is quickly followed by a content update.
- Updating GitHub
actions/cacheto v4.
- Fixed behavior change introduced in 15.0.0 where scrolling could animate when
UIView.areAnimationsEnabledisfalse.
- Programmatic scrolling animations could be janky.
- Introduce
ListStateObserver.onDidEndDeceleration(_:)callback, which allows an observer to become notified when the scrollview finishes deceleration.
- CocoaPods is no longer a supported installation method, and new releases will no longer be published to CocoaPods. Please switch to using Swift Package Manager to install Listable.
AutoScrollAction.scrollTo(_:onInsertOf:position:animation:shouldPerform:didPerform:)has been changed to no longer take an animation block, and renamed toAutoScrollAction.scrollTo(_:onInsertOf:position:animated:shouldPerform:didPerform:), taking aBoolanimatedparameter instead.
- While no longer published, CocoaPods is still used for demo project generation.
- Added
CacheCleanerwhich exposes a method to force Listable's static caches to be cleared.
animatesChangesnow always defaults totrue.
BlueprintUIListsnow depends onBlueprintUI5.0.0.
- Added new
isScrollEnabledproperty toBehaviorto disable scrolling on a list if needed.
- Revert: Fixed an issue where animations would occur when dequeuing / reusing cells. A layout is now forced without animation before presentation.
- Fixed an issue where animations would occur when dequeuing / reusing cells. A layout is now forced without animation before presentation.
- You may now control list update animations with the
ListAnimationtype.
BlueprintUIListsnow depends onBlueprintUI4.0.0.
ListReorderGestureno longer blocks child accessibility, now exposing a proxy element for accessible control.
- Fixed an issue that could cause a crash during view reuse when the list contained different types of headers.
- Generated documentation now uses a static copyright notice to avoid noisy diffs.
- Fixed a bug that resulted in some swipe action buttons not being tappable.
- Fix SPM dependency on listable
- Fixed a bug that resulted in header/footer views not properly updating, by fixing the underlying tracking of collection view supplementary views.
- Update the swipe action interactions to more closely match iOS behavior.
- Maximum button size for
.sizeThatFitsstyle is now 120pts - Button text can span up to two lines now
- Automatically adjust text size for text that is too long
- Touching anywhere outside of the cell will close swipe actions
- Tapping inside of a cell with open swipe actions will close them
- Allow the panning gesture to remain interactive even when swipe actions are open
- Maximum button size for
- Updated deployment target from iOS 14.0 to iOS 15.0.
- Bumped CI to use Xcode 15.1.
- Updated Gems and set Ruby version to 3.2.2.
- Fixed an issue where supplementary views (headers or footers) that contained a first responder would result in the view being duplicated when scrolled off-screen.
- Fixed an issue where a crash would occur when applying an external update to list content while a live reorder event was occurring.
- Remove override of
performBatchUpdatesfrom our internalUICollectionViewsubclass, it causes warnings for consumers.
KeyboardObserverhas been updated to handle iOS 16.1+ changes that use the screen's coordinate space to report keyboard position. This can impact reported values when the app isn't full screen in Split View, Slide Over, and Stage Manager.- The
verticalLayoutGravitybehavior now takes into accountframechanges so that the scroll position relative to the bottom remains unchanged when theframechanges.
KeyboardObserverDelegatenow providesUIView.AnimationCurveinstead ofUIView.AnimationOptions.
ApplyItemContentInfoandApplyHeaderFooterContentInfoare now available in the BlueprintEnvironmentfor eachBlueprintItemContent.- A new
isContentScrollableproperty is added toListViewto determine if the content size is large enough that the list can be scrolled to a new position without springing back to it's original position. - A new
customcase is added toKeyboardAdjustmentModewhich allows the consumer to fully customize the inset behavior.onKeyboardFrameWillChangeandcustomScrollViewInsetshave been added toListViewandupdateScrollViewInsetsis now public. All of these can be utilized in conjunction to respond to the keyboard and fully control the insets. For now, these are available throughListViewonly. - A new
verticalLayoutGravitybehavior to accomodate vertical-layout lists where the normal scroll position of the list is at the bottom of the list. SettingverticalLayoutGravityto.bottomenables the new behavior. It's designed to accomodate a messaging client. Adds a new demo called Chat App.
SwipeActionproperty names have been updated to better reflect what they're for.Completionalso now takes in a more descriptive enum, instead of a boolean, to make reading callsites clearer. Eg,completion(.expandActions)instead ofcompletion(true).
- Update CI script to reference the
xcodesorg/made/xcodespackage for installing simulator runtimes. - Update CI script to install
aria2to improve simulator runtime download speeds.
.pagedlayout'sitemInsetshas been removed; usebounds.paddinginstead.
.pagedlayouts now respectboundsfor each page.
- Enabled collection view first responder workaround for iOS 17.0; it is broken in the first beta.
- You may now programatically reveal leading and trailing swipe actions, by calling the
showLeadingSwipeActionsorshowTrailingSwipeActionsclosures onApplyItemContentInfo.
- Fixed a confusing compilation error when omitting the
.contentproperty on read-onlyKeyPathlookups onListProperties.
- Added optional underlay view for item cells that can be styled
- BlueprintUILists now depends on Blueprint 2.0.
- Fix an issue when a header or footer has an
onTaphandler, and no pressed background, the first tap would be ignored.
- Swipe actions will now use the
accessibilityLabel(if non-nil) when the user is using assistive technologies such as VoiceOver.
- Added
containerCornerRadius,equalButtonWidths, andminWidthtoDefaultSwipeActionsView.Stylefor additional swipe action style customization. - Added
swipeActionsViewStyletoListEnvironment. This allows aSwipeActionsView.Styleto be set on the list environment when customizing the appearance of the swipe action view. - Added the ability to configure leading swipe actions on
Items via theleadingSwipeActionsproperty. - Added
containerCornerRadius,buttonSizing,minWidth, andmaxWidthRatiotoDefaultSwipeActionsView.Stylefor additional swipe action style customization. - Added
SwipeActionsView.Style.leadingContainerInsetsto specify container insets for the leading swipe action container.
- Removed the
SwipeActionsViewassociated type onItemContent. - Removed the
ItemContentSwipeActionsViewprotocol.
- Renamed
DefaultSwipeActionsViewtoSwipeActionsView. - The type of the
ItemContent.swipeActionsStyleprotocol requirement is nowSwipeActionsView.Style?(previouslySwipeActionsView.Style). When an item returnsnilfor this property the style set on the list environment will be used instead. - Renamed
Item.swipeActionstoItem.trailingSwipeActions. - Renamed
DefaultItemProperties.swipeActionstotrailingSwipeActions. - Renamed
SwipeActionsView.Style.containerInsetstoSwipeActionsView.Style.trailingContainerInsetsand changed the type toNSDirectionalEdgeInsets. - Renamed
SwipeActionsView.StyletoSwipeActionsViewStyle. SwipeActionsViewandSwipeActionStateare no longer public types.
- Improvement: Background and Selected Background views for rows and section headers will not be created unless requested. This reduces the overall number of views being allocated.
Listadheres to Blueprint's new sizing contract when running in Caffeinated Layout mode.
- BlueprintUILists now depends on Blueprint 1.0.
- Introduce
ListStateObserver.onDidEndDeceleration(_:)callback, which allows an observer to become notified when the scrollview finishes deceleration. - Introduce
ListStateObserver.OnDidBeginDrag(_:)callback, which allows an observer to become notified when the scrollview will begin dragging.
- A small defensive update to the iOS 16.4 Collection View workaround.
-
Fixed an issue that could cause the wrong swipe action view style being applied when multiple styles were used in a single list.
-
Fixed a regression in iOS 16.4, where on every collection view refresh, the collection view would force resign a first responder if it was within a header or footer (cells are not affected). See
ListView+iOS16.4Workaround.swiftfor more.
- Introduce an
OverlayDecoration, which allows you to place a border, etc, around an item which is not affected by swipe action position.
- Updated
BlueprintUIandBlueprintUICommonControlsto version0.50.0.
- Do not call auto scroll action didPeform blocks if the scroll action did not succeed.
- Speculative, low effort fix for a scrolling crash that occurred when the list view was under high update load, with many changes enqueued.
- Updated
BlueprintUIandBlueprintUICommonControlsto version0.49.0.
- Fix Catalyst version specifier in SPM package.
-
iOS 12 and 13 have been deprecated.
-
Marks pod as
APPLICATION_EXTENSION_API_ONLY -
KeyboardObserveris now a SPI accessible API- When using SPM, you are responsible for initializing this singleton in non-extension contexts
ListView.configure(with: application)should be called when your app has finished launching- Failure to do so will continue to
print()the existing LISTABLE WARNING
- Fixed an issue where submitting many frequent updates in a large list would cause crashes due to state getting out of sync, hopefully.
- You may now control the stickiness of headers within individual sections, eg by setting
section.layouts.table.isHeaderSticky = true/false/nil, or by implementingisStickySectionHeaderon yourHeaderFooterContent. Providing nil for either value falls back to the list-level stickiness setting.
ListHeaderPosition.fixedwill now only apply if the list's top padding is zero, to avoid the header shifting around during layout if the position is changed.
- Revert from 7.0.0: "When a section is inserted or removed, and that section has only one item, and no header or footer, the insertion or removal animation for the section's singular item will be used instead." This was causing crashes in
initialLayoutAttributesForAppearingItemandfinalLayoutAttributesForDisappearingItemdue to index path mismatches.
- Fixed an issue where
rowSpacingwas used instead ofitemSpacinginFlowListLayout. - Fixed SPM-based builds.
- Fixed an issue where
rowSpacingwas used instead ofitemSpacinginFlowListLayout.
-
Behavior.decelerationRate- Controls the rate at which scrolling decelerates. The default value,normal, maintains the status quo. -
ListPagingBehavior.firstVisibleItemCentered- When the user stops scrolling, the final offset of the scroll event will be adjusted so that the first visible item is centered within the visible bounds.
-
Introduces a
.togglesselection type, to allow a second tap to deselect an item. -
Swipe actions will now dismiss when touching outside of the actively swiped cell to match iOS behavior.
- Removed RetailGridListLayout.
- When a section is inserted or removed, and that section has only one item, and no header or footer, the insertion or removal animation for the section's singular item will be used instead.
- Fixed an issue where
ListHeaderPosition.fixedwould cause the list header to overlap with the refresh control by falling back tostickybehavior if there's a refresh control.
SwipeActionnow allows you to provide anaccessibility{Label,Value,Hint}, and requires either atitleoraccessibilityLabel.
- The refresh control color has moved to
AppearancefromRefreshControl.
- Fix a crash when initializing
Item.
DefaultItemPropertiesandDefaultHeaderFooterPropertiesnow have all properties for each ofItemandHeaderFooter.
- Fixed an issue where
ListHeaderPosition.fixedwould cause the list header to overlap with the container header by falling back tostickybehavior if there's a container header. - Supplementary items will now animate when their position in the layout changes.
- Fix an issue where horizontal list views would erroneously inset for the keyboard. Horizontal lists should not adjust for the keyboard, since it ends up causing vertical scrolling.
- Added a tint color to
SwipeActionto configureDefaultSwipeActionsView. This allows customization of the text and image color (assuming a template image is used), where previously they were always white.
- Ensure
Optionalvalues fromDefaultItemPropertiesandDefaultHeaderFooterPropertiesare respected.
Listmeasurement now has options to include thesafeAreaInsetsfrom theEnvironmentif thecontentInsetAdjustmentBehaviorwill affect the layout.
stickyListHeaderhas been replaced withlistHeaderPosition, which has three possible values:inline,sticky, andfixed.
- Fixed a bug where child accessibility views could be exposed when they should be hidden.
- Added
stickyListHeaderto layout / appearance, allowing you to pin list headers to the top of the content.
- Ensure supplementary views are properly reused.
- Supplementary views will now properly animate (fade) in and out when they are added or removed.
- Introduce
ContentContext, anEquatablevalue which represents the overall context for all content presented in a list. Eg, you might pass a theme here, the traits for your screen (eg, dark mode, a11y settings, etc), or any other value which when changed, should cause the entire list to re-render. If theContentContextchanges across list renders, all list measurements will be thrown out and re-measured during the next render pass.
- Added a pinning option
pin(to:)which is very similar toscrollToItem(onInsertOf:)except that you don't specify anonInsertOfitem. - Adds a
bottomScrollOffsetproperty toListScrollPositionInfo. You can use this to fine-tune pinning by only pinning when within a certain distance of the bottom scroll position.
-
Enabled accessibility ordering, but only propagating the accessibility label reordering is possible and VoiceOver is active to avoid conflicting matches in KIF tests.
-
containerHeadersin table and flow layouts now stretch to fill the available width of the view. Previously, they were inset with the content.
- When using
BlueprintUILists, layout is no longer forced during element updates. This will cause animations to no longer be inherited. Please use.transition, etc. to control animations.
- Removed item reordering with VoiceOver as it caused issues with KIF tests.
- Fixed list measurements with container headers.
- Item reordering is now possible when using VoiceOver.
ListReorderGesture.Beginsadded. This controls when the reorder gesture starts:onTapandonLongPress.
TableAppearance.ItemLayoutnow properly initializes theitemToSectionFooterSpacingvalue.- A swipe actions memory leak has been fixed for
ItemCell.ContentContainerView.
LayoutDescriptionnow conforms toEquatable.ListLayoutAppearancenow has afuncto modify the default layout.- You can now construct a layout description from a
ListLayoutAppearance, allowing the underlyingListLayoutto remain internal to a module.
- The signature of
ListLayout.layout(delegate:in:)has been changed to return aListLayoutResultvalue, to make it clearer which values must be provided as the output of a layout.
- When measuring a
Listin an unconstrained size constraint, and.fillParentis passed, a better assertion message is provided.
- Ensure that
.fillParentListmeasurements returns the right height.
-
You may now set the
contentInsetAdjustmentBehavioron.tablelayouts. This is useful when presenting in a sheet, to more directly control the safe area inset. -
You can now control underflow bounce behavior on
.tablelayouts, viabounceOnUnderflow.
- Insert and removal animations for items now respect
UIAccessibility.isReduceMotionEnabled, falling back to.fadeifisReduceMotionEnabledis true.
-
Added support for
.horizontal.tablelayouts. To get a horizontal table; just set thelayout.direction = .horizontalwhen configuring your list's layout. Additionally, some properties were renamed from left/right to leading/trailing to better reflect they can now be on the left/top and right/bottom of a list view, respectively. -
Expose
layoutAppearancePropertiesonLayoutDescription, to access standard layout appearance properties without creating an instance of the backing layout. -
The
.flowlayout type has been added, to support flow and grid style layouts. -
ListView.contentSizewill now also provide access to the natural width of a layout if the layout supports natural width calculation. This is useful, for example, to show a.tablelayout in a popover – you can now know how wide to render the popover. -
Added
.pagingBehaviourto.tableand.flowstyle layouts, which allows implementing carousel-style layouts, by enabling scroll paging alongside item boundaries.
-
The
.experimental_gridlayout type has been removed; it is replaced by.flow. -
Default sizes have been removed. Please ensure your elements correctly implement
sizeThatFits, or use fixed sizes.
-
scrollViewPropertieshas moved fromListLayouttoListLayoutAppearance. -
The various
.table { ... },.paged { ... }, etc,LayoutDescriptionfunctions no longer take an escaping closure. -
preconditionis now overridden withinListableUIandBlueprintUIListsto point at an inlined function, which calls through tofatalError. This ensures that error messages are reported in crash reports.
- Fix keyboard inset calculations by using
adjustedContentInset.
-
Added support for result builders when creating lists, sections, and swipe actions:
List { Section("id") { ExampleContent(text: "First Item") ExampleContent(text: "Second Item") } header: { ExampleHeader(title: "This Is My Section") } footer: { ExampleFooter(text: "Rules apply. Prohibited where void.") } }
ListLayoutand its associated types are now public, allowing you to make custom layouts. Note that these APIs are still experimental and subject to change.
- Ensure we properly pass through the
ListEnvironmentwhen updating on-screen views.
- Fixed an erroneous
weakreference inSupplementaryContainerViewwhich lead to contents being deallocated too early – this is not actually needed.HeaderFooterViewStatePairholds the reference to the containedAnyPresentationHeaderFooterState, there are not direct strong references fromAnyPresentationHeaderFooterStatetoSupplementaryContainerView.
- Ensure that when comparing header/footer types during updates, we are comparing the correct underlying types in a
type(of:)check.
- Introduced
swipeActionsStyleproperty inItemContentprotocol. This allows clients to configure and specify different visual styles for swipe action views (such asroundedswipe actions).
onTaponHeaderFooternow takes no parameters, to disambiguate it fromconfigure.
-
Introduced
AnyHeaderFooterConvertibleforHeaderFooterscontained in lists and sections, so you no longer need to wrap yourHeaderFooterContentin aHeaderFooterto receive default values. Eg, you can now do:section.header = MyHeaderContent(title: "Albums")
Instead of:
section.header = HeaderFooter(MyHeaderContent(title: "Albums"))
- Change the default sizing of
ItemandHeaderFooterto.thatFits(.noConstraint)from requiring the min from the layout. This is more common for self-sizing cells.
clearsSelectionOnViewWillAppearwas moved toListViewController.
- Includes fix for header reuse from 0.25.1.
- You can now provide default list bounds for participating layouts via the
environment.listContentBoundsproperty. This allows your containing screen, eg, to provide default bounds to ensure content lays out correctly. Thetableandgridlayout types have been updated to read these content bounds.
ListSizingwas renamed toList.Measurement, to reflect that it affects measurement and to align with Blueprint's terminology for measurement.
- Add support for
containerHeader, a header which can be added by the container which is displaying the list. This is useful for, eg, a custom navigation controller to add its large title view to the list's content. This header is not affected by the list's vertical padding.
- Add support for
ReappliesToVisibleView, which allows controlling when an on-screen view should have its content re-applied.
- Ensure that scroll actions work with horizontal lists.
- Fix two reordering crashes, which could happen when 1) a reorder signal resulted in an immediate deletion at the end of the list, and 2) a crash during scrolling during a reorder event.
- Introduce
defaultHeaderFooterPropertiesonHeaderFooterContent, to allow specifying default values for aHeaderFooterwhen values are not passed to the initializer.
- Fixed
identifier(for:)onSectionto match name ofidentifier(with:)onItemContent.
- Fixed
Identifiableconformance forItemContent.
- Listable now depends on Blueprint
0.27.0which has major breaking changes. There are no public changes to Listable, except public interfaces determined by Blueprint protocol conformance.
- When applying an update to visible views during content updates, the update now occurs within an animation block. This allows your view to inherit implicit animations more easily.
- Reordering between multiple sections is now supported.
- Introduced type safe access to
Sectioncontent following reorder events. SeeSection.filtered. ListStateObserver.onItemReorderedwas added to observe reorder events at a list-wide level.ListLayoutwas extended to allow customization of in-progress moves. Note thatListLayoutis not yet public.
Reorderinghas been renamed toItemReordering, and a newSectionReorderinghas been introduced. This allows finer-grained control over validating reorder events at both the item level and section level.ListReorderGestureandItemReordering.GestureRecognizerhave been heavily refactored to reduce visibility of internal state concerns.Item.identifierhas been renamed toItem.anyIdentifier. The newItem.identifierproperty is now a fully type safe identifier.ReorderingActionswas refactored to expose less public state and ease use in UIView-backed list elements.Identifier<Represented>is nowIdentifier<Represented, Value>; egIdentifier<MyContent, UUID>. This is done to support reacting to reordering events in a more type safe manner, and to makeIdentifiercreation more type safe. This is a large breaking change.- Changed how
identifiers forItemContentare represented.ItemContentnow returns a an identifier of a specificIdentifierValue(eg,String,UUID, etc), which is then assembled into anIdentifierby the containing item. Additional APIs have been added for creatingIdentifiers in a more type safe manner. This is a large breaking change.
- Fixed the spacing between the header and the first section of a
TableListLayoutto not add the top padding.
- Changed how
ListView.contentSizeis implemented in order to improve performance. An internal list is no longer used, instead we create a layout and ask it to lay out its elements.List.Measurementalso moved toBlueprintUILists, as that is the only place it was used.
- Add support for adjusting the content offset when the refresh control becomes visible with the
offsetAdjustmentBehaviorproperty.
Example usage:
list.content.refreshControl = RefreshControl(
isRefreshing: isRefreshing,
offsetAdjustmentBehavior: .displayWhenRefreshing(animate: true, scrollToTop: true),
onRefresh: onRefresh
)
- When calling
scrollToItemwith a.topscroll position, the item no longer appears underneath sticky section headers.
- Adds
scrollToSectiontoListActionsandListView. To support this functionality,Sectioncan now be queried with anIdentifier. Also addedSectionPositionto specify the top or bottom within aSection.
Example usage:
listActions.scrolling.scrollToSection(
with: MyItem.identifier(with: id),
sectionPosition: .top,
scrollPosition: ScrollPosition(position: .centered)
)
-
When swiping to delete, limit overscrolling to 20% of the cell width. This prevents undesirable visual state while maintaining swipe bounciness. Additionally, ignore initial swipes to the right which do not "open" the cell.
-
Fixed a crash that occurred when the list's width or height would become zero.
- Updates to
ItemContentCoordinatorto properly support animations in Blueprint-backed rows. This change also generalizes the contained animation type toViewAnimation, for use in both scrolling and content updates.
- When updating
contentInset, retain the values pulled from theCollectionView. This is to avoid clobbering the content inset potentially set by other things like navigation controllers.
- Rename
buildparameters toconfigure, in order to be more consistent within the framework and with Blueprint.
- Fix a memory leak in
ListViewthat caused allListViewswith content in them to leak.
-
Introduce support for layout customization for
Item,HeaderFooter, andSectionfor allListLayouttypes, not just.table. -
Add
insertedandremoveditems to.onContentChanged, to easily determine what content was added or removed from the list a central location.
- Rename
.listlayout to.table, which is clearer, and also reduces confusion betweenListLayout(the base protocol for layouts), and the specific table-type layout.
SwipeActionsConfiguration.performsFirstActionWithFullSwipeis now respected when set tofalse.
-
Ensure that
ItemContents andHeaderFooters are a value type. This is generally assumed by Listable, but was previously not validated. This is only validated inDEBUGbuilds, to avoid otherwise affecting performance. -
Fix a regression that caused content to be re-measured during each application of an
Appearance, even if the newAppearancewas equal.
- Adds a way to create items or header/footers for Blueprint lists without requiring the creation of a
BlueprintItemContentorBlueprintHeaderFooterContent.
- Introduce
LocalizedItemCollator, a list-friendly version ofUILocalizedIndexedCollationwhich allows collating a list of content at one time.
-
Changed behavior of
scrollInsets(nowscrollIndicatorInsets), which now only affects the scroll indicator insets of the contained scroll view, and does not affect the content inset of the scroll view. Please usingpadding, etc, on the various list layout types instead to control visual padding. -
Ensure we respect both
frameandboundschanges to update the innerCollectionView's frame. We previously used to only respectframechanges, but we should also respectboundschanges, as these are used by auto layout. -
Fix support for
autolayoutitems and headers/footers by ensuring we pass through the correctsystemLayoutSizeFittingcalls to content. Add assertions that measured sizing is within a reasonable bound. -
Appearance.backgroundColornow respects the currentUITraitCollection.userInterfaceStyle. This means that the background color will default towhitein light mode, andblackin dark mode. -
Update
ListView.contentSize(in:for:)to properly validate the providedfittingSize. This ensures that.unconstrainedmeasurements along the wrong axis will now assert; instead of freeze.
-
Introduce
onSelectionChangedonListStateObserverto allow observing when the selected rows change. -
Pass through
BlueprintUI.Environmentto theElements being rendered fromBlueprintItemContentandBlueprintHeaderFooterContent. This ensures that the content you put into aListrespects theBlueprintUI.Environmentof theListitself. This PR also introducesListEnvironmentto facilitate this, which allows similar passthrough of environment variables within Listable. -
Add a
didPerformcallback toAutoScrollAction, which allows registering a callback when an auto scroll action occurs. -
Change
animatedoption on scrolling to ananimationoption, to allow customizing the animation's behavior.
- Allow setting the
sizingtype on aList. This controls how the list should be sized by Blueprint: Should it take up all allowed space, or should it size to fit based on its content.
- Fixed import of Swift bridging header, so Cocoapods can build with or without
use_frameworks!.
- Adjust calculated keyboard inset in both
setFrameandlayoutSubviews. This resolves issues that can occur if the list frame changes while the keyboard is visible.
- Add support for
onInsert,onRemove,onMove,onUpdate, onItemto track when when items are added, removed, moved, or updated. ChangedonContentChangedtoonContentUpdatedonListStateObserver; it is always called during updates; you can check thehadChangesproperty.
- Removed support for iOS 10. Future releases will only support iOS 11 and later.
-
Change how keyboard are observed to avoid a pitfall where the keyboard would not be accounted for if a
ListViewis created while a keyboard is already on screen. To avoid this problem, we switch to a globally sharedKeyboardObserverwhich is loaded at app startup time. -
isEmptyonContentandSectionhave been replaced withcontains(any:), which allows more granular comparison of the content in the whole list and in individual sections, respectively. This allows you to check if the list or sections contain headers, footers, items, all, or some combination of them. -
Listable has been renamed to ListableUI, and BlueprintLists is now named BlueprintUILists. This is done to be more consistent with other Square UI libraries, and to avoid a conflict with an existing published Cocoapod, also named Listable.
-
Simplify
Sizingnow that enums support default associated values.. Now instead of separate.thatFitsand.thatFitsWith(Constraint)enums, there is a single.thatFits(Constraint = .noConstraint)case (the same applies forautolayout). -
Changed how
zIndexesare assigned to header and items, and support tapping headers / footers. This allows registering anonTaphandler for any HeaderFooter, and providing a background to display while the tap's press is active.
-
Add support for
ListStateObserverso that you can observe changes made to the list such as insertions, removals, scroll events, etc. -
Add support for
ListActionswhich allows performing actions on the underlying list view when used in a declarative environment, or when you otherwise do not have access to the underlying view instance (ListStateViewController). -
Add support for Behavior.KeyboardAdjustmentMode, which allows for disabling automatic keyboard adjustment behavior. This is useful if your container view is managing the size of or insets on a
ListViewitself. -
Introduced
callAsFunctionsupport when building with Xcode 11.4 or later. This allows you to replace code like this:List { list in list += Section("first") { section in ... } }With this:
List { list in list("first") { section in ... } }Improving terseness when building sections in a list.
-
.paged()is now a supported layout type. This allows implementing your list to render similarly to aUIPageViewController, in either horizontal or vertical alignment.
- Removed support for .
horiztonallayouts on.table()layouts. Now only.verticalis supported (this could return at a later date if needed).
-
Changed
Sectioninitialization APIs fromSection(identifier: "my-id") { ... }toSection("my-id") { ... }– it's clear from the API what the first param is for, so the param name just made callsites longer. -
Renamed
setContentandsetPropertiesmethods onListViewtoconfigure. -
Significant refactors to how the custom layout APIs work. While this is mostly an internal concern, it continues to refine these APIs to set them up for public exposure and usage at a later date to customize layouts.
- Significant performance improvements for list updates which contain either no changes, or only in-place updates to existing items and sections. In many cases, these updates will now be 80% faster. This change also improves performance for other types of changes such as insertions, removals, or moves, but not to the same degree.
-
Added additional layout configuration options:
headerToFirstSectionSpacingandlastSectionToFooterSpacingnow let you control the spacing between the list header and content, and the content and the list footer. -
Add support for snapshot testing
Items via theItemPreviewViewclass. This is a view type which takes in some configuration options, and anItem, which you can then use in snapshot tests to verify the appearance of yourItemandItemContent.let view = ItemPreviewView() view.update( with: 300.0, state: .init(isSelected: false, isHighlighted: false), item: Item(MyItemContent(...)) ) self.takeSnapshot(of: view) -
Add support for Xcode previews via the
ItemPreviewtype. This allows easy previewing yourItemContentduring development like so:struct ElementPreview : PreviewProvider { static var previews: some View { ItemPreview.withAllItemStates( for: Item(XcodePreviewDemoContent( text: "Lorem ipsum dolor sit amet (...)" )) ) } }There are included options like
withAllItemStateswhich allow seeing previews across the various possible selection and highlight states. -
Add
customInterSectionSpacingproperty toSection.Layoutwhich allows the user to specify custom spacing after a section, overriding the calculated spacing. -
Add
insertAndRemoveAnimationstoItemto allow customizing the animations used when anItemis inserted or removed from a list. Note that customizing this option when responding toSwipeActionswill come at a later date. -
Add
ListViewControllermake it easy to create view controllers backed by a ListableListView.
-
Update
Itemcallbacks to allow for providing more info to the callback parameters. -
ListAppearance.Layout.paddingis now applied around all content in the list, not only around sections. To regain the previous behavior, useheaderToFirstSectionSpacingandlastSectionToFooterSpacing. -
Significantly change how layout configuration is done to make it clearer which type of layout is currently in use, and which options are available on which layouts.
Previously, to configure a layout, you would write code like this:
list.appearance.layoutType = .table list.appearance.table.layout.padding = UIEdgeInsets(...)Now, you configure the layout like this:
list.layout = .table { $0.layout.padding = UIEdgeInsets(...) }Or, for your custom layouts, like this:
list.layout = MyCustomLayout.describe { $0.myLayoutsProperty = .foo }
- Change
Item'sonSelectandonDeselectto be performed asynchronously after a single runloop spin, to giveUICollectionViewtime to schedule animations if these callbacks are slow. - Add improved signpost logging for selection and deselection, to more easily identify slow callbacks.
- Fixed multiple selection and highlight issues: Highlighting cells now only occurs if the
selectionStyleistappableorselectable. Ensure that whentappableis provided, the content of a cell is updated when the cell is deselected.
- Added type aliases for
HeaderFooterandHeaderFooterContentto reduce verbosity of use. Now instead of typingHeaderFooter(MyHeader()), you can useHeader(MyHeader()). - Replace unused / experimental
Bindingtype withCoordinator, which allows you to independently manage item state in a similar manner to SwiftUI'sUIViewRepresentable'sCoordinator.
- Major Change:
ItemElementandHeaderFooterElementwere renamed toItemContentandHeaderFooterContent, respectively. This is intended to be a clearer indicaton as to what they are for (the content of an item or header/footer), and fixes a name collision with Blueprint, where we overloaded the meaning ofElementwhen using Blueprint integration viaBlueprintUILists. - Changed
BlueprintHeaderFooter{Content/Element}'s main method to beelementRepresentationinstead ofelement. This allows easier conformance ofBlueprintUI.ProxyElementtypes toBlueprintHeaderFooter{Content/Element}. SelectionModewas moved fromContenttoBehavior, which is in line with other collection view behaviours like scrolling and underflow.- Rename
ItemSelectionStyle.nonetoItemSelectionStyle.notSelectable. This is to avoid conflicts withOptional.nonewhen working withItemSelectionStyleas anOptional.
- Added support for conditionally scrolling to items on insert, based on the
shouldPerformblock passed to theAutoScrollAction.
Earlier releases were ad-hoc and not tracked. To see all changes, please reference closed PRs on Github.