DEV Community

Denys Telezhkin
Denys Telezhkin

Posted on

What's new in DTTableView/CollectionViewManager 11

11.0 is a next major release of DTTableViewManager and DTCollectionViewManager frameworks, bringing not one, but two SwiftUI integrations, support for datasource prefetching, enhanced macCatalyst support, as well as updates for iOS 16 / tvOS 16 SDK.

Table of contents

Support for SwiftUI views in cells

I strongly believe SwiftUI is a future of UI development on Apple platforms. Unfortunately, I also believe, that this future is not fully here yet. SwiftUI is very powerful, but has lots of issues, that require attention from Apple developers, as well as time in order to drop old OS releases like iOS 13 and macOS Catalina where SwiftUI is in very rough state.

SwiftUI is also not a full replacement for all UIKit / AppKit components, as they have much more functionality than SwiftUI can support at this very moment. Those components include UITableView and UICollectionView. While being partially replaced by SwiftUI List, LazyVStack, LazyHStack and LazyVGrid / LazyHGrid, UITableView and UICollectionView in some places provide much more functionality and performance than their SwiftUI counterparts. However, where SwiftUI completely dominates, is in layout, which is much more powerful and simple than AutoLayout.

So in DTTableViewManager 11, we are bridging two worlds, and taking best from both of them - SwiftUI view layout and UIKit performance and functionality.

iOS 13 and higher

Apple officially introduced support for SwiftUI in table and collection view cells on iOS 16 with UIHostingConfiguration, which is now supported by DTTableViewManager (read more about this below). However, for those of us (me included), who are not yet ready to jump to iOS 16 deployment target, DTTableView/CollectionViewManagers provide new methods to host SwiftUI in table and collection view cells on iOS 13 and higher:

manager.registerHostingCell(for: Post.self) { post, indexPath in
    PostSwiftUIView(post: post)
}
Enter fullscreen mode Exit fullscreen mode

This integrations comes with some caveats, that you need to be aware of.

First of all, this is not officially supported by Apple, which means that UITableView and UICollectionView will not know anything about what is hosted in the cells. This means, that you need to either provide estimated sizes for cells, or match the size of cells in UIKit with sizes you use in SwiftUI, otherwise layout systems will go to war with each other, producing unexpected results.

Secondly, while in AppKit there is NSHostingView, UIKit does not have UIHostingView, and needs to rely on UIHostingController instead. This may come with some surprises, because UIHostingController in some cases tries to avoid keyboard and adjust for safe area insets, which is obviously not needed in a view hosted in UITableViewCell.

While those issues are present not only in table and collection view cells (but actually anywhere you want to use UIHostingController), we still need a way to work around those. To do that, you can use a custom subclass of UIHostingController, for example:

manager.registerHostingCell(for: Post.self) { model, _ in
    PostSwiftUICell(model: model)
} mapping: { mapping in
    mapping.configuration.hostingControllerMaker = {
        ControlledNavigationHostingController(rootView: $0) 
    }
}
Enter fullscreen mode Exit fullscreen mode

You can read about all customization options for SwiftUI configuration in a separate document.

In my experience, with some minor adjustments to UIHostingController and cell sizing, SwiftUI views in cells seem to be working great, and I definitely recommend trying those.

iOS 16 and higher

If you are ready to drop support for old OS-es now, DTTableViewManager now integrates with iOS 16 API - UIHostingConfiguration:

manager.registerHostingConfiguration(for: Post.self) { cell, post, indexPath in
    UIHostingConfiguration {
        PostView(post: post)
    }
}
Enter fullscreen mode Exit fullscreen mode

Because this is officially supported way of integrating SwiftUI with table and collection view cells, I highly recommend watching WWDC 2022 session video on this topic.

All customization options for UIHostingConfiguration are fully supported, for example you can customize margins for cell content:

manager.registerHostingConfiguration(for: Post.self) { cell, post, indexPath in
    UIHostingConfiguration {
        PostView(post: post)
    }.margins(.horizontal, 16)
}
Enter fullscreen mode Exit fullscreen mode

Additionally, you can also use UICellConfigurationState of a cell by simply adding one additional parameter:

manager.registerHostingConfiguration(for: Post.self) { state, cell, post, indexPath in
    UIHostingConfiguration {
        PostView(post: post, isSelected: state.isSelected)
    }
}
Enter fullscreen mode Exit fullscreen mode

Datasource prefetching

I'm quite late to the party of datasource prefetching, but better late, than never, right? :)

Datasource prefetching is now supported with two additional event methods:

manager.register(PostCell.self) { mapping in
    mapping.prefetch { model, indexPath in 
        // start prefetching for model
    }
    mapping.cancelPrefetch { model, indexPath in 
        // cancel prefetching for model
    }
}
Enter fullscreen mode Exit fullscreen mode

Please note, that while UITableViewDataSourcePrefetching and UICollectionViewDataSourcePrefetching call prefetching methods with array of indexPaths, DTTableViewManager and DTCollectionViewManager call prefetching events for a single data model, using forEach loop. This should make management of prefetching operations easier.

If, however, you prefer receiving array of index paths, as with all delegate methods, you can absolutely do that by simply implementing UITableViewDataSourcePrefetching methods on your DTTableViewManageable instance (typically view controller with tableView, where you access DTTableViewManager).

Enhanced macCatalyst support

While macCatalyst was supported for a while, now instead of just building frameworks for macCatalyst, DTTableViewManager runs full iOS test suite on CI for both Xcode 13 and Xcode 14.

This will make sure, that macCatalyst builds are not broken with future releases.

Please note, that while iOS 16 was released with Xcode 14, macCatalyst 16 will be released with Xcode 14.1 along with macOS Ventura later this fall, so previously mentioned UIHostingConfiguration support is not available with macCatalyst and Xcode 14.0.

If you want to test new functionality with macCatalyst - use Xcode 14.1 beta for that.

Xcode 14 and iOS 16 SDK

As every year, DTTableViewManager and DTCollectionViewManager are adding support for new delegate methods, and deprecating events / delegate methods, that were deprecated in iOS SDK itself. Here's a list for this year:

Added:

  • UITableViewDelegate.tableView(_:canPerformPrimaryActionForRowAt:)
  • UITableViewDelegate.tableView(_:performPrimaryActionForRowAt:)
  • UICollectionViewDelegate.collectionView(_:canPerformPrimaryActionForItemAt:)
  • UICollectionViewDelegate.collectionView(_:performPrimaryActionForItemAt:)
  • UICollectionViewDelegate.collectionView(_:contextMenuConfigurationForItemsAt:point:)
  • UICollectionViewDelegate.collectionView(_:contextMenuConfiguration:highlightPreviewForItemAt:
  • UICollectionViewDelegate.collectionView(_:contextMenuConfiguration:dismissalPreviewForItemAt:

Deprecated on iOS 16:

  • UICollectionViewDelegate.collectionView(_:contextMenuConfigurationForItemAt:point:)
  • UICollectionViewDelegate.collectionView(_:previewForHighlightingContextMenuWithConfiguration:)
  • UICollectionViewDelegate.collectionView(_:previewForDismissingContextMenuWithConfiguration:)

Thanks

That's it folks! Thanks to all users of the frameworks, and everyone reading this document!

If you are interested in full list of changes, read DTTableViewManager changelog or DTCollectionViewManager changelog.

If you encounter issues with frameworks, please don't hesitate to open issue, or submit a pull request.

Have a good day, everyone!

Top comments (0)