-
-
Save rdavisau/20bfa9e46e89cf31d409f8796cc41cf1 to your computer and use it in GitHub Desktop.
public static class DiffableDataSourceExtensions | |
{ | |
public static NSDiffableDataSourceSnapshot<IdentifierType<TSection>, IdentifierType<TItem>> | |
ToDiffableDataSourceSnapshot<TSection, TSectionIdentifier, TItem, TItemIdentifier>( | |
this IEnumerable<TSection> sections, Func<TSection, TSectionIdentifier> getSectionIdentifier, | |
Func<TSection, IEnumerable<TItem>> getItems, Func<TItem, TItemIdentifier> getItemIdentifier) | |
{ | |
var snapshot = new NSDiffableDataSourceSnapshot<IdentifierType<TSection>, IdentifierType<TItem>>(); | |
foreach (var section in sections) | |
{ | |
var items = getItems(section); | |
var sectionIdentifier = IdentifierType.For(section, getSectionIdentifier); | |
var itemIdentifiers = items.Select(item => IdentifierType.For(item, getItemIdentifier)).ToArray(); | |
snapshot.AppendSections(new[] { sectionIdentifier }); | |
snapshot.AppendItems(itemIdentifiers); | |
} | |
return snapshot; | |
} | |
} |
public class EasyUITableViewDiffableDataSource<TSection, TSectionIdentifier, TItem, TItemIdentifier> | |
: UITableViewDiffableDataSource<IdentifierType<TSection>, IdentifierType<TItem>>, IUITableViewDiffableDataSource<TSection> | |
{ | |
Func<TSection, TSectionIdentifier> _getSectionIdentifier; | |
Func<TSection, IEnumerable<TItem>> _getSectionItems; | |
Func<TItem, TItemIdentifier> _getItemIdentifier; | |
Func<UITableView, int, TSection, string> _titleForHeader; | |
Func<UITableView, int, TSection, string> _titleForFooter; | |
NSDiffableDataSourceSnapshot<IdentifierType<TSection>, IdentifierType<TItem>> _snapshot; | |
public EasyUITableViewDiffableDataSource( | |
UITableView tableView, | |
Func<TSection, TSectionIdentifier> getSectionIdentifier, | |
Func<TSection, IEnumerable<TItem>> getSectionItems, | |
Func<TItem, TItemIdentifier> getItemIdentifier, | |
UITableViewDiffableDataSourceCellProvider cellProvider, | |
Func<UITableView, int, TSection, string> titleForHeader = null, | |
Func<UITableView, int, TSection, string> titleForFooter = null | |
) : base(tableView, cellProvider) | |
{ | |
_getSectionIdentifier = getSectionIdentifier; | |
_getSectionItems = getSectionItems; | |
_getItemIdentifier = getItemIdentifier; | |
_titleForHeader = titleForHeader; | |
_titleForFooter = titleForFooter; | |
} | |
public void ApplySnapshot(IEnumerable<TSection> sections, bool animatingDifferences) | |
{ | |
_snapshot = sections.ToDiffableDataSourceSnapshot( | |
_getSectionIdentifier, _getSectionItems, _getItemIdentifier); | |
ApplySnapshot(_snapshot, animatingDifferences); | |
} | |
public override string TitleForHeader(UITableView tableView, nint section) | |
=> _titleForHeader?.Invoke(tableView, (int)section, _snapshot.SectionIdentifiers[section].Item); | |
public override string TitleForFooter(UITableView tableView, nint section) | |
=> _titleForFooter?.Invoke(tableView, (int)section, _snapshot.SectionIdentifiers[section].Item); | |
} |
public static class EasyUITableViewDiffableDataSource | |
{ | |
public static IUITableViewDiffableDataSource<TSection> Create<TSection, TSectionIdentifier, TItem, TItemIdentifier>( | |
UITableView tableView, | |
List<TSection> items, | |
Func<TSection, TSectionIdentifier> getSectionIdentifier, | |
Func<TSection, IEnumerable<TItem>> getSectionItems, | |
Func<TItem, TItemIdentifier> getItemIdentifier, | |
Func<UITableView, NSIndexPath, TItem, UITableViewCell> getCell, | |
Func<UITableView, int, TSection, string> titleForHeader = null, | |
Func<UITableView, int, TSection, string> titleForFooter = null) | |
=> new EasyUITableViewDiffableDataSource<TSection, TSectionIdentifier, TItem, TItemIdentifier> | |
( | |
tableView, getSectionIdentifier, getSectionItems, getItemIdentifier, | |
(tv, indexPath, item) => getCell(tv, indexPath, (item as IdentifierType<TItem>).Item), | |
titleForHeader, titleForFooter | |
); | |
} |
public class FuncIdentifierType<T,U> : IdentifierType<T> | |
{ | |
private readonly Func<T, U> _identifierFunc; | |
public FuncIdentifierType(T item, Func<T,U> identifierFunc) : base(item) | |
{ | |
_identifierFunc = identifierFunc; | |
} | |
// invoke the provided func and hash the result | |
public override nuint GetNativeHash() | |
=> (nuint)_identifierFunc(Item).GetHashCode(); | |
public override bool IsEqual(NSObject anObject) | |
=> GetNativeHash() == anObject.GetNativeHash(); | |
} |
public static class IdentifierType | |
{ | |
public static IdentifierType<T> For<T>(T item) => new IdentifierType<T>(item); | |
public static IdentifierType<T> For<T,U>(T item, Func<T, U> getIdentifier) => new FuncIdentifierType<T,U>(item, getIdentifier); | |
} | |
public class IdentifierType<T> : NSObject | |
{ | |
public readonly T Item; | |
public IdentifierType(T item) | |
{ | |
Item = item; | |
} | |
// pass-through the .NET hash | |
public override nuint GetNativeHash() | |
=> (nuint) Item.GetHashCode(); | |
public override bool IsEqual(NSObject anObject) | |
=> GetNativeHash() == anObject.GetNativeHash(); | |
} |
public interface IIdentifier | |
{ | |
string Identifier { get; } | |
} | |
public class IIdentifierType<T> : IdentifierType<T> | |
where T: IIdentifier | |
{ | |
public IIdentifierType(T item) : base(item) {} | |
// read the identifier and take its hash | |
public override nuint GetNativeHash() | |
=> (System.nuint)Item.Identifier.GetHashCode(); | |
public override bool IsEqual(NSObject anObject) | |
=> GetNativeHash() == anObject.GetNativeHash(); | |
} |
public interface IUITableViewDiffableDataSource<TSection> | |
{ | |
void ApplySnapshot(IEnumerable<TSection> sections, bool animatingDifferences); | |
} |
public static NSDiffableDataSourceSnapshot<IdentifierType<TSection>, IdentifierType<TItem>> | |
ToDiffableDataSourceSnapshot<TSection, TSectionIdentifier, TItem, TItemIdentifier>( | |
this IEnumerable<TSection> sections, Func<TSection, TSectionIdentifier> getSectionIdentifier, | |
Func<TSection, IEnumerable<TItem>> getItems, Func<TItem, TItemIdentifier> getItemIdentifier) | |
{ | |
var snapshot = new NSDiffableDataSourceSnapshot<IdentifierType<TSection>, IdentifierType<TItem>>(); | |
foreach (var section in sections) | |
{ | |
var items = getItems(section); | |
var sectionIdentifier = IdentifierType.For(section, getSectionIdentifier); | |
var itemIdentifiers = items.Select(item => IdentifierType.For(item, getItemIdentifier)).ToArray(); | |
snapshot.AppendSections(new[] { sectionIdentifier }); | |
snapshot.AppendItems(itemIdentifiers); | |
} | |
return snapshot; | |
} |
public class IdentifierType<T> : NSObject | |
{ | |
public readonly T Item; | |
public IdentifierType(T item) | |
{ | |
Item = item; | |
} | |
// pass-through the .NET hash | |
public override nuint GetNativeHash() | |
=> (nuint) Item.GetHashCode(); | |
public override bool IsEqual(NSObject anObject) | |
=> GetNativeHash() == anObject.GetNativeHash(); | |
} |
var source = | |
EasyUITableViewDiffableDataSource.Create( | |
TableView, | |
items: Games, // used for type inference, can be null at the time of the call | |
getSectionIdentifier: game => game.GameName, // return key for section | |
getSectionItems: game => game.Characters, // return items for section | |
getItemIdentifier: character => character.CharacterName, // return key for item | |
getCell: (tv, indexPath, character) => // standard GetCell, but includes typed model parameter (character) | |
{ | |
// yeah yeah cell reuse | |
var cell = new UITableViewCell(UITableViewCellStyle.Default, "cell"); | |
cell.TextLabel.Text = character.CharacterName; | |
return cell; | |
}, | |
titleForHeader: (tv, sectionIndex, section) => section.GameName); |
Thank you for this article
I have error at this line
IdentifierType.For(section, getSectionIdentifier);
What is For méthod? is this an extension?
Do you have a full sample?
Thank you for your help
@am-kh Unfortunately I don't have the sample from the blogpost anymore.
Looks like this gist was missing at least one file which I have just added - IdentifierType.cs
. If you add this hopefully you are up and running.
Yes! Thank you a lot.
Tell me, is it possible to have Hot Reload with Xamarin.iOS or the new Microsoft.iOS?
I saw you had it in your videos.
It will be great. Thank you !
@am-kh I added a small ios sample and quick video if it helps. The main issue at the moment is the 'register attribute' hack; since I am doing some Microsoft.iOS work soon I will improve this aspect. I improved that and updated the sample.
The code is super helpful and your article explained the diffable data sources much better than "native" articles about them! Thanks a lot!