DTTableViewManager 8.0 is the latest major release of UITableView library for iOS and tvOS written in Swift. Following Semantic Versioning conventions, 8.0 introduces API-breaking changes.
- Unified and improved cell/view registration methods
- New compact type-safe way of registering event closures.
- Support for using unsubclassed
UITableViewCell
/UITableViewHeaderFooterView
withoutModelTransfer
conformance.
- iOS 11.0 and higher / tvOS 11.0 and higher
- Xcode 12 and higher
- Swift 5.3 and higher
- DTModelStorage 9.0 and higher
In previous releases you needed to specify cell type multiple times, when registering cell, and when registering each event. Now, you can register events for this mapping in mapping
closure:
// Previous releases
manager.register(PostCell.self)
manager.didSelect(PostCell.self) { cell, model, indexPath in
// tableView(_:didSelectRowAt:)
}
manager.willDisplay(PostCell.self) { cell, model, indexPath in
// tableView(_:willDisplay:forRowAt:)
}
// New
manager.register(PostCell.self) { mapping in
mapping.didSelect { cell, model, indexPath in
// tableView(_:didSelectRowAt:)
}
mapping.willDisplay { cell, model, indexPath in
// tableView(_:willDisplay:forRowAt:)
}
}
Those events are now tied to ViewModelMapping
instance, which means, that events, registered this way, will only trigger, if mapping condition of current mapping applies. For example:
manager.register(PostCell.self) { mapping in
mapping.condition = .section(0)
mapping.didSelect { cell, model, indexPath in
// This closure will only get called, when user selects cell in the first section
}
}
manager.register(PostCell.self) { mapping in
mapping.condition = .section(1)
mapping.didSelect { cell, model, indexPath in
// This closure will only get called, when user selects cell in the second section
}
}
New event closure registration now plays much more nicely with Xcode autocomplete, because of focused method visibility. For example, when you register events for UITableViewCell
, you will not see UITableViewHeaderFooterView
events in autocomplete, as well as events, not tied to cell / view.
Please note, that new event style registration is only available for
UITableViewHeaderFooterView
and subclasses.
Since library creation, ModelTransfer
was a protocol, upon which all mapping/registration/event closures relied on. It was not possible to use library without conforming your cell subclasses to this protocol.
DTTableViewManager
removes this restriction:
manager.register(UITableViewCell.self, for: String.self) { mapping in
} handler: { cell, model, indexPath in
cell.textLabel.text = model
}
Header/footer views also support the same syntax:
manager.registerHeader(UITableViewHeaderFooterView.self, for: String.self) { mapping in
} handler: { header, model, indexPath in
}
You can actually mix and match cells with ModelTransfer
protocol conformance and without, in the same UITableView
.
Please note, that for non-ModelTransfer views, only new style event registration - through
mapping
closure is available.
Example project contains view controller, that was setup using new cell and event registration styles.
In previous DTTableViewManager
releases, there were a lot of cell/view registration methods, some for registering nibless views, some with custom nibs etc. In order to simplify and unify registration methods, as well as introduce new ones, most of registration variants have been deprecated, and xib / xibless registration methods are being merged into one method.
For example, new cell registration method looks like this:
manager.register(PostCell.self) { mapping in
// customize mapping
} handler: { cell, model, indexPath in
// configure cell with model.
}
This registration works for xib-less cell registration as well as registering PostCell
xib. handler
closure replaces previously available configureCell
closure, which is now deprecated.
New syntax is backwards-compatible with old syntax without closures:
manager.register(PostCell.self)
-mapping
andhandler
closures are optional.
ViewModelMapping
class has been reworked from the ground up to allow holding generic information about reusable views and cells, as well as dequeuing configured views.
MemoryStorage
now has insertItems(_:at:)
method, that allows inserting collection starting from provided indexPath. This is useful for example if you show a list of items and a load more button/spinner, and want to insert new page of items between old items and paging cell:
try? manager.memoryStorage.insertItems(newPosts, at: IndexPath(item: self.numberOfItems - 1, section: 0))
ViewModelMapping
now has a new convenience method modelCondition
for conditional mappings:
manager.register(OddCell.self) { mapping in
mapping.condition = mapping.modelCondition { indexPath, model in
return indexPath.item.isOdd
}
}
Along with API reference, there is now extensive documentation, broken into sections for your convenience. It covers board range of topics, including datasources, events, mapping/registration and more.
This release requires Swift 5.3. Minimum iOS / tvOS deployment targets are unchanged (iOS 11, tvOS 11).
This release heavily relies on where clauses on contextually generic declarations, that are only available in Swift 5.3 - SE-0267.
configureCell
, configureHeader
, configureFooter
methods have been deprecated and are being replaced with handler
parameter on registration methods.
// previous releases
manager.register(PostCell.self)
manager.configureCell(PostCell.self) { cell, model, indexPath in
cell.selectionStyle = .none
}
// 8.x release
manager.register(PostCell.self) { cell, model, indexPath in
cell.selectionStyle = .none
}
Please note, that
handler
closure is called beforeModelTransfer.update(with:)
method
Several cell/header/footer view registration methods have been deprecated to unify registration logic. Please use register(_:mapping:handler:)
, registerHeader(_:mapping:handler:)
and registerFooter(_:mapping:handler:)
as a replacements for all of those methods.
Some examples of replacement API's for deprecated methods:
// Old
manager.registerNibless(PostCell.self)
// New
manager.register(PostCell.self)
// Old
manager.registerNibNamed("FooCell", for: PostCell.self)
// New
manager.register(PostCell.self) { mapping in
mapping.xibName = "FooCell"
}
DTTableViewManager.configureEvents(for:_:)
is deprecated, it's functionality has become unnecessary since mapping closure of cell/header/footer registration now captures both cell and model type information for such events.DTTableViewManager.configureDiffableDataSource(modelProvider:)
is deprecated for non-hashable data models. Please use configureDiffableDataSource method for models, that are Hashable. From Apple's documentation:If you’re working in a Swift codebase, always use UITableViewDiffableDataSource instead
.TableViewUpdater.usesLegacyTableViewUpdateMethods
property.