Skip to content

Commit

Permalink
Add migration guide.
Browse files Browse the repository at this point in the history
  • Loading branch information
DenTelezhkin committed Aug 18, 2019
1 parent afae6d4 commit ca582fe
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 1 deletion.
18 changes: 17 additions & 1 deletion DTTableViewManager.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@
/* Begin PBXFileReference section */
3EBF90E122E7640500135C10 /* DiffableDatasourcesTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableDatasourcesTestCase.swift; sourceTree = "<group>"; };
3EBF90E422E7643900135C10 /* BaseTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTestCase.swift; sourceTree = "<group>"; };
3EC8F87C2309810A00FF3C7A /* DTTableViewManager 6.0 Migration Guide.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "DTTableViewManager 6.0 Migration Guide.md"; sourceTree = "<group>"; };
3EC8F87D2309810A00FF3C7A /* DTTableViewManager 4.x Migration Guide.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "DTTableViewManager 4.x Migration Guide.md"; sourceTree = "<group>"; };
3EC8F87E2309810A00FF3C7A /* DTTableViewManager 5.0 migration guide.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "DTTableViewManager 5.0 migration guide.md"; sourceTree = "<group>"; };
3EC8F87F2309813E00FF3C7A /* 7.0 Migration Guide.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "7.0 Migration Guide.md"; sourceTree = "<group>"; };
3ED770A022E3211200C0E3A6 /* students.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = students.json; sourceTree = "<group>"; };
3ED770A322E3236400C0E3A6 /* MultiSectionDiffingTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MultiSectionDiffingTableViewController.swift; path = "Example controllers/MultiSectionDiffingTableViewController.swift"; sourceTree = "<group>"; };
3EDC205322B817E00078EB0D /* DTTableViewDragDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DTTableViewDragDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -306,6 +310,17 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
3EC8F87B2309810A00FF3C7A /* Guides */ = {
isa = PBXGroup;
children = (
3EC8F87C2309810A00FF3C7A /* DTTableViewManager 6.0 Migration Guide.md */,
3EC8F87F2309813E00FF3C7A /* 7.0 Migration Guide.md */,
3EC8F87D2309810A00FF3C7A /* DTTableViewManager 4.x Migration Guide.md */,
3EC8F87E2309810A00FF3C7A /* DTTableViewManager 5.0 migration guide.md */,
);
path = Guides;
sourceTree = "<group>";
};
3EDC205122B817E00078EB0D /* Sources */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -544,11 +559,12 @@
9A383CA51CE1DA2F0081D843 /* Default-568h@2x.png */,
9AD92BED1BE266D700E667FF /* Documentation */,
9A9B17031B65771600D8ABD3 /* Example */,
9AFAAF7C22D4C9A6001C86B0 /* Frameworks */,
3EC8F87B2309810A00FF3C7A /* Guides */,
9A88F5A819EAC683008436C9 /* Images.xcassets */,
E6EA83631615EE6000F8B8C3 /* Products */,
3EDC205122B817E00078EB0D /* Sources */,
9A383C821CE1CC5F0081D843 /* Supporting files */,
9AFAAF7C22D4C9A6001C86B0 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down
143 changes: 143 additions & 0 deletions Guides/7.0 Migration Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# DTTableViewManager 7.0 Migration Guide

DTTableViewManager 7.0 is the latest major release of UITableView helper library for iOS and tvOS written in Swift. Following [Semantic Versioning conventions](https://semver.org), 7.0 introduces API-breaking changes.

This guide is provided in order to ease the transition of existing applications using 6.x versions to the latest APIs, as well as explain the design and structure of new and updated functionality.

- [Requirements](#requirements)
- [Benefits of Upgrading](#benefits-of-upgrading)
- [Breaking API Changes](#breaking-api-changes)
- [Supplementary providers](#supplementary-providers)
- [DTTableViewManageable](#DTTableViewManageable)
- [Other breaking changes](#other-breaking-changes)
- [New Features](#new-features)
- [Diffable datasources](#diffable-datasources)
- [iOS 13 API](#ios-13-api)
- [Bugfixes and improvements](#bugfixes-and-improvements)

## Requirements

- iOS 8.0 and higher / tvOS 9.0 and higher
- Xcode 9.x and higher
- Swift 4.0 and higher
- [DTModelStorage](https://github.com/DenTelezhkin/DTModelStorage) 8.0 and higher

## Benefits of Upgrading

- **Support for Diffable DataSources in iOS / tvOS 13**.
- **Unified supplementary model API**
- **Support for new iOS 13 delegate API**

## Breaking API Changes

### Supplementary providers

In previous releases various storages from `DTModelStorage` had several API's to work with headers and footers. This could create confusion to how those APIs should be used, as well as prevented support for diffable datasources, which delegate construction of sections to developer. So starting with DTModelStorage 8.0, header and footer API has been rewritten to be closure-based. You can read more about those changes in [DTModelStorage 8.0 Migration Guide](https://github.com/DenTelezhkin/DTModelStorage/blob/master/Guides/8.0%20Migration%20Guide.md)

Regarding `DTTableViewManager` part of those changes, there are several important things to remember:

* Setting header and footer models does not trigger `UITableView.reloadData()` anymore, so it needs to be called manually if you need to update headers/footers when this method is called. If you set header/footer providers before UITableView comes on screen, calling reloadData is not necessary.
* Setting header/footer models no longer creates sections in storage. If storage does not contain sections, even if `TableViewConfiguration.displayHeaderOnEmptySections` property is set to true, header will not be displayed until some items are set in the storage. If you want to create section with 0 items, in case you use `MemoryStorage`, you can for example call `memoryStorage.setItems([Int](), forSectionAt: emptySectionIndex)`
* `SupplementaryAccessible` protocol with corresponding extensions `tableHeaderModel` and `tableFooterModel` has been removed. If you need to get header/footer model from section, call `storage.header/footerModel(for:)` method.

### DTTableViewManageable

`DTTableViewManageable` is a protocol, that is implemented to let `DTTableViewManager` know, how to communicate with `UITableView`. Previously, there was a second protocol - `DTTableViewOptionalManageable` to allow working with `UITableView`, that is declared as optional.

In 7.0 release `DTTableViewOptionalManageable` protocol has been removed and it's functionality has been merged into `DTTableViewManageable`, which now has two properties:

* `tableView`
* `optionalTableView`

One of those properties (it does not matter which one), is required to return a non-nil `UITableView` instance for `DTTableViewManager` to work.

### Other breaking changes

Previously deprecated `ViewModelMappinCustomizing` protocol has been removed. Please use [conditional mappings feature](https://github.com/DenTelezhkin/DTTableViewManager/blob/master/Guides/DTTableViewManager%206.0%20Migration%20Guide.md#conditional-mappings) instead.

`tableViewUpdater` is now an optional property and will contain nil, if diffable datasources are used.

## New Features

### Diffable datasources

Diffable datasources is a cool new feature, that is introduced in UIKit in iOS / tvOS 13. `DTTableViewManager 7` provides a powerful integration layer with it, but in order to understand how this layer works, it's highly recommended to check out great [Advances in UI Data Sources WWDC session](https://developer.apple.com/videos/play/wwdc2019/220/).

If you don't use `DTTableViewManager`, you would typically create diffable datasource like so (taken from Apple's sample code on diffable datasources):

```swift
dataSource = UICollectionViewDiffableDataSource
<Section, MountainsController.Mountain>(collectionView: mountainsCollectionView) {
(collectionView: UICollectionView, indexPath: IndexPath,
mountain: MountainsController.Mountain) -> UICollectionViewCell? in
guard let mountainCell = collectionView.dequeueReusableCell(
withReuseIdentifier: LabelCell.reuseIdentifier, for: indexPath) as? LabelCell else {
fatalError("Cannot create new cell") }
mountainCell.label.text = mountain.name
return mountainCell
}
```

One of `DTTableViewManager`s main goals is to get rid of String identifiers, and to handle cell creation, as well as updating cell with it's model, for you. Which is why with DTTableViewManager 7 code, equivalent to one above, is the following:

```swift
dataSource = manager.configureDiffableDataSource { indexPath, model in
return model
}
```

As before, `ModelTransfer` protocol is used to deliver data model to the cell:

```swift
class MountainCell: UITableViewCell, ModelTransfer {
@IBOutlet weak var titleLabel: UILabel!

func update(with model: Mountain) {
titleLabel.text = model.name
}
}
}
```

You should persist strong reference to `dataSource` object, and use it for constructing sections and items exactly as described in Apple documentation and WWDC session.

Diffable datasources and `DTTableViewManager 7` are tightly integrated, so all events, even datasource ones like `manager.configure(_:)`, continue to work in the same way as they were working before.

On top of that, there is an additional functionality, that currently `UITableViewDiffableDataSource` class does not provide. It's currently not possible to use it and have section titles/headers/footers in `UITableView`. With `DTTableViewManager` however, it works just as you would expect:

```swift
manager.supplementaryStorage?.setSectionHeaderModels(["Foo"])
```

Both events and section header/footer integration is possible, because `DTTableViewManager` injects a special `ProxyDiffableDataSourceStorage` object between `UITableViewDiffableDataSource` and `UITableView`. This storage does not store data models and just queries diffable data source to receive them. It does, however, implement section header and footer model providers, which unlocks possibility to have section titles/headers/footers when using diffable datasources.

`DTTableViewManager` supports both generic `UITableViewDiffableDataSource<SectionType,ItemType>` and non-generic `UITableViewDiffableDataSourceReference` with the same method name(`configureDiffableDataSource`). Resulting diffable datasource type is inferred from your declaration of the datasource.

### iOS 13 API

iOS 13 SDK has a few new delegate methods for UITableView, and they are wrapped in event closures:

* `shouldBeginMultipleSelectionInteraction`
* `didBeginMultipleSelectionInteraction`
* `didEndMultipleSelectionInteraction`
* `contextMenuConfiguration(for:)`
* `previewForHighlightingContextMenu`
* `previewForDismissingContextMenu`
* `willCommitMenuWithAnimator`

Also, events for several methods that were deprecated in iOS 13 SDK, are now deprecated in DTTableViewManager:

* `editActions(for:)`
* `shouldShowMenuForItemAt`
* `canPerformAction`
* `performAction`

## Bugfixes and improvements

There is a bunch of bugfixes and improvements in this release, including:

* Support for custom bundles for cells/headers/footers
* Ability to implement table view header/footer views on your DTTableViewManageable type, bypassing storage
* Improved handling for `displayHeader/FooterOnEmptySection`, that does not ask for header/footer height anymore, if section is empty.

For more, please read a [detailed changelog](https://github.com/DenTelezhkin/DTTableViewManager/blob/master/CHANGELOG.md).

0 comments on commit ca582fe

Please sign in to comment.