What's new in DTTableView/CollectionViewManager 11
Tags: uitableview, uicollectionview, swiftui, swift
Published: 2022-10-06 12:46:51

11.0 is a next major release of [DTTableViewManager](https://github.com/DenTelezhkin/DTTableViewManager) and [DTCollectionViewManager](https://github.com/DenTelezhkin/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](#support-for-swiftui-views-in-cells)
    - [iOS 13 and higher](#ios-13-and-higher)
    - [iOS 16 and higher](#ios-16-and-higher)
- [Datasource prefetching](#datasource-prefetching)
- [Enhanced macCatalyst support](#enhanced-maccatalyst-support)
- [Xcode 14 / iOS 16 / tvOS 16](#xcode-14-and-ios-16-sdk
)

## 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:

```swift
manager.registerHostingCell(for: Post.self) { post, indexPath in
    PostSwiftUIView(post: post)
}
```

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:

```swift
manager.registerHostingCell(for: Post.self) { model, _ in
    PostSwiftUICell(model: model)
} mapping: { mapping in
    mapping.configuration.hostingControllerMaker = {
        ControlledNavigationHostingController(rootView: $0) 
    }
}
```
You can read about all customization options for SwiftUI configuration in a [separate document](https://github.com/DenTelezhkin/DTTableViewManager/blob/main/Documentation/SwiftUI.md).

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`:

```swift
manager.registerHostingConfiguration(for: Post.self) { cell, post, indexPath in
    UIHostingConfiguration {
        PostView(post: post)
    }
}
```

Because this is officially supported way of integrating SwiftUI with table and collection view cells, I highly recommend watching [WWDC 2022 session video](https://developer.apple.com/videos/play/wwdc2022/10072/) on this topic. 

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

```swift
manager.registerHostingConfiguration(for: Post.self) { cell, post, indexPath in
    UIHostingConfiguration {
        PostView(post: post)
    }.margins(.horizontal, 16)
}
```

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)
    }
}
```

## 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:

```swift
manager.register(PostCell.self) { mapping in
    mapping.prefetch { model, indexPath in 
        // start prefetching for model
    }
    mapping.cancelPrefetch { model, indexPath in 
        // cancel prefetching for model
    }
}
```

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](https://github.com/DenTelezhkin/DTTableViewManager/releases) or [DTCollectionViewManager changelog](https://github.com/DenTelezhkin/DTCollectionViewManager/releases).

If you encounter issues with frameworks, please don't hesitate to [open issue](https://github.com/DenTelezhkin/DTTableViewManager/issues/new), or [submit a pull request](https://github.com/DenTelezhkin/DTTableViewManager/compare). 

Have a good day, everyone!