- During the two-year period from iOS13-iOS14 we have seen a number of changes coming from Apple regarding the
UICollectionView
and thetype
associated with it. Not only are the newAPI
introduced, but some of theconcept
and concepts that were used tobuild
collectionview
have been changed and updated according to newprogramming
models. In this article we will cumgf explore the new models to further understand how thesecollection
work.
1: Diffable data sources:
- One of the problems we have often encountered when working with
collection view
on systems pre-iOS13
comes from the real-world scenarios when all updates need to be manually deployed bydeveloper
(like usageperformBatchUpdates
). The manual implementation above often causes appcrash
when theupdate
do not end up concurrently with thedata model
being used. - Using
UICollectionViewDiffableDataSource
means that we will let thatclass
calculate the change in thecollection view
‘s state and automaticallyupdate
the necessary changes to thedata
display. - We take the example of
ProductListViewController
display theproduct
. Toviewcontroller
useDiffableDataSource
then first we must initialize acellProvider
closure
to transferindexPath
forUICollectionViewCell
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeDataSource</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewDiffableDataSource</span> <span class="token operator"><</span> <span class="token builtin">Section</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token function">UICollectionViewDiffableDataSource</span> <span class="token punctuation">(</span> collectionView <span class="token punctuation">:</span> collectionView <span class="token punctuation">,</span> cellProvider <span class="token punctuation">:</span> <span class="token punctuation">{</span> collectionView <span class="token punctuation">,</span> indexPath <span class="token punctuation">,</span> product <span class="token keyword">in</span> <span class="token keyword">let</span> cell <span class="token operator">=</span> collectionView <span class="token punctuation">.</span> <span class="token function">dequeueReusableCell</span> <span class="token punctuation">(</span> withReuseIdentifier <span class="token punctuation">:</span> <span class="token keyword">Self</span> <span class="token punctuation">.</span> cellReuseID <span class="token punctuation">,</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> indexPath <span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token operator">!</span> <span class="token builtin">ListCollectionViewCell</span> cell <span class="token punctuation">.</span> textLabel <span class="token punctuation">.</span> text <span class="token operator">=</span> product <span class="token punctuation">.</span> name <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token keyword">return</span> cell <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Using
Swift strong type
way on ensuringtype safe
for themodel data
as well as enabling us cancustom
the typeHashable
definitions forSection
instead of always usingInt
:
1 2 3 4 5 6 7 8 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">enum</span> <span class="token builtin">Section</span> <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">,</span> <span class="token builtin">CaseIterable</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> featured <span class="token keyword">case</span> onSale <span class="token keyword">case</span> all <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- What we need to do now is we need to
assign
data
to thecollection view
like we did before:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">class</span> <span class="token class-name">ProductListViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">let</span> cellReuseID <span class="token operator">=</span> <span class="token string">"product-cell"</span> <span class="token keyword">private</span> <span class="token keyword">lazy</span> <span class="token keyword">var</span> collectionView <span class="token operator">=</span> <span class="token function">makeCollectionView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">private</span> <span class="token keyword">lazy</span> <span class="token keyword">var</span> dataSource <span class="token operator">=</span> <span class="token function">makeDataSource</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token keyword">override</span> <span class="token keyword">func</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">.</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Registering our cell class with the collection view</span> <span class="token comment">// and assigning our diffable data source to it:</span> collectionView <span class="token punctuation">.</span> <span class="token function">register</span> <span class="token punctuation">(</span> <span class="token builtin">ListCollectionViewCell</span> <span class="token punctuation">.</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> forCellWithReuseIdentifier <span class="token punctuation">:</span> <span class="token keyword">Self</span> <span class="token punctuation">.</span> cellReuseID <span class="token punctuation">)</span> collectionView <span class="token punctuation">.</span> dataSource <span class="token operator">=</span> dataSource <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> |
- Once the
data model
have beenupdate
we need to add adescribe
of thecurrent view
states to thedataSource
so that thecell
can automatically track andupdate
as needed. - We will use the
snapshop
concept for thesection
defined and update eachsection
from thedata model
. Finally we take thesnapshot
dataSource
by updating thecollection view
after comparing the previous change:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">productListDidLoad</span> <span class="token punctuation">(</span> <span class="token number">_</span> list <span class="token punctuation">:</span> <span class="token builtin">ProductList</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> snapshot <span class="token operator">=</span> <span class="token builtin">NSDiffableDataSourceSnapshot</span> <span class="token operator"><</span> <span class="token builtin">Section</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> snapshot <span class="token punctuation">.</span> <span class="token function">appendSections</span> <span class="token punctuation">(</span> <span class="token builtin">Section</span> <span class="token punctuation">.</span> allCases <span class="token punctuation">)</span> snapshot <span class="token punctuation">.</span> <span class="token function">appendItems</span> <span class="token punctuation">(</span> list <span class="token punctuation">.</span> featured <span class="token punctuation">,</span> toSection <span class="token punctuation">:</span> <span class="token punctuation">.</span> featured <span class="token punctuation">)</span> snapshot <span class="token punctuation">.</span> <span class="token function">appendItems</span> <span class="token punctuation">(</span> list <span class="token punctuation">.</span> onSale <span class="token punctuation">,</span> toSection <span class="token punctuation">:</span> <span class="token punctuation">.</span> onSale <span class="token punctuation">)</span> snapshot <span class="token punctuation">.</span> <span class="token function">appendItems</span> <span class="token punctuation">(</span> list <span class="token punctuation">.</span> all <span class="token punctuation">,</span> toSection <span class="token punctuation">:</span> <span class="token punctuation">.</span> all <span class="token punctuation">)</span> dataSource <span class="token punctuation">.</span> <span class="token function">apply</span> <span class="token punctuation">(</span> snapshot <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- It should be noted here is that we are moving the model
Product
directlydataSource
byconfirm
Hashable
. The above approach is problematic if we have adata model
that cannotconfirm
the aboveprotocol
so we can pass some formatting to thedataSource
and then proceed to the completemodel
in thecellProvider
closure.
2: Cell registrations:
Cell registrations
is a newconcept
iniOS14
allows us to identify the usage of theUICollectionViewCell
subclass as well as how we customize thecollectionview cell
with complex objects. We won’t need to remember having to declarecell
types themselves for thereuse identifier
job and cells won’t needtype casting
.- We will use the new
API
toimplement
theregistration
andconfiguration
for thecollectionview cell
with theProductListViewController
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">typealias</span> <span class="token builtin">Cell</span> <span class="token operator">=</span> <span class="token builtin">ListCollectionViewCell</span> <span class="token keyword">typealias</span> <span class="token builtin">CellRegistration</span> <span class="token operator">=</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">.</span> <span class="token builtin">CellRegistration</span> <span class="token operator"><</span> <span class="token builtin">Cell</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token keyword">func</span> <span class="token function">makeCellRegistration</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">CellRegistration</span> <span class="token punctuation">{</span> <span class="token builtin">CellRegistration</span> <span class="token punctuation">{</span> cell <span class="token punctuation">,</span> indexPath <span class="token punctuation">,</span> product <span class="token keyword">in</span> cell <span class="token punctuation">.</span> textLabel <span class="token punctuation">.</span> text <span class="token operator">=</span> product <span class="token punctuation">.</span> name <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- We can review the
makeDataSource
method and changecellProvider
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeDataSource</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewDiffableDataSource</span> <span class="token operator"><</span> <span class="token builtin">Section</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">let</span> cellRegistration <span class="token operator">=</span> <span class="token function">makeCellRegistration</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">UICollectionViewDiffableDataSource</span> <span class="token punctuation">(</span> collectionView <span class="token punctuation">:</span> collectionView <span class="token punctuation">,</span> cellProvider <span class="token punctuation">:</span> <span class="token punctuation">{</span> collectionView <span class="token punctuation">,</span> indexPath <span class="token punctuation">,</span> product <span class="token keyword">in</span> collectionView <span class="token punctuation">.</span> <span class="token function">dequeueConfiguredReusableCell</span> <span class="token punctuation">(</span> using <span class="token punctuation">:</span> cellRegistration <span class="token punctuation">,</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> indexPath <span class="token punctuation">,</span> item <span class="token punctuation">:</span> product <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- We have just significantly improved the previous
code
withcellProvider
closure that directly takes over cellregistration
. We’ll need to add anextension
here:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">extension</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">.</span> <span class="token builtin">CellRegistration</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> cellProvider <span class="token punctuation">:</span> <span class="token punctuation">(</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">,</span> <span class="token builtin">IndexPath</span> <span class="token punctuation">,</span> <span class="token builtin">Item</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Cell</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> collectionView <span class="token punctuation">,</span> indexPath <span class="token punctuation">,</span> product <span class="token keyword">in</span> collectionView <span class="token punctuation">.</span> <span class="token function">dequeueConfiguredReusableCell</span> <span class="token punctuation">(</span> using <span class="token punctuation">:</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> indexPath <span class="token punctuation">,</span> item <span class="token punctuation">:</span> product <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- With the above
extension
we have reduced the number of lines of code above as follows:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeDataSource</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewDiffableDataSource</span> <span class="token operator"><</span> <span class="token builtin">Section</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token function">UICollectionViewDiffableDataSource</span> <span class="token punctuation">(</span> collectionView <span class="token punctuation">:</span> collectionView <span class="token punctuation">,</span> cellProvider <span class="token punctuation">:</span> <span class="token function">makeCellRegistration</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> cellProvider <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
3: Compositional layouts:
- Before
iOS13
we had two options to customize the layout forUICollectionView
. The first way is to useUICollectionViewFlowLayout
and we’ll go through the first steps of this selection: - We need clear definitions for
compositional layout
including: items, groups, sections. Item for thelayout
ofcell
, groups for layering cells together and sectionsexes that include sections forcollectionview
. - We want the
layout
for the product list views withfeatured
andonSale
sections using 2column grid
while the sections are usingfull-width
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeGridLayoutSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">NSCollectionLayoutSection</span> <span class="token punctuation">{</span> <span class="token comment">// Each item will take up half of the width of the group</span> <span class="token comment">// that contains it, as well as the entire available height:</span> <span class="token keyword">let</span> item <span class="token operator">=</span> <span class="token function">NSCollectionLayoutItem</span> <span class="token punctuation">(</span> layoutSize <span class="token punctuation">:</span> <span class="token function">NSCollectionLayoutSize</span> <span class="token punctuation">(</span> widthDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalWidth</span> <span class="token punctuation">(</span> <span class="token number">0.5</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> heightDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalHeight</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token comment">// Each group will then take up the entire available</span> <span class="token comment">// width, and set its height to half of that width, to</span> <span class="token comment">// make each item square-shaped:</span> <span class="token keyword">let</span> group <span class="token operator">=</span> <span class="token builtin">NSCollectionLayoutGroup</span> <span class="token punctuation">.</span> <span class="token function">horizontal</span> <span class="token punctuation">(</span> layoutSize <span class="token punctuation">:</span> <span class="token function">NSCollectionLayoutSize</span> <span class="token punctuation">(</span> widthDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalWidth</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> heightDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalWidth</span> <span class="token punctuation">(</span> <span class="token number">0.5</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> subitem <span class="token punctuation">:</span> item <span class="token punctuation">,</span> <span class="token builtin">count</span> <span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NSCollectionLayoutSection</span> <span class="token punctuation">(</span> group <span class="token punctuation">:</span> group <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The strong point of
compositional layout
is that we can use multiple layouts within aviewcontroller
as well as we candescribe
desiredlayout
usingfractional values
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeListLayoutSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">NSCollectionLayoutSection</span> <span class="token punctuation">{</span> <span class="token comment">// Here, each item completely fills its parent group:</span> <span class="token keyword">let</span> item <span class="token operator">=</span> <span class="token function">NSCollectionLayoutItem</span> <span class="token punctuation">(</span> layoutSize <span class="token punctuation">:</span> <span class="token function">NSCollectionLayoutSize</span> <span class="token punctuation">(</span> widthDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalWidth</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> heightDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalHeight</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token comment">// Each group then contains just a single item, and fills</span> <span class="token comment">// the entire available width, while defining a fixed</span> <span class="token comment">// height of 50 points:</span> <span class="token keyword">let</span> group <span class="token operator">=</span> <span class="token builtin">NSCollectionLayoutGroup</span> <span class="token punctuation">.</span> <span class="token function">vertical</span> <span class="token punctuation">(</span> layoutSize <span class="token punctuation">:</span> <span class="token function">NSCollectionLayoutSize</span> <span class="token punctuation">(</span> widthDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">fractionalWidth</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> heightDimension <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token function">absolute</span> <span class="token punctuation">(</span> <span class="token number">50</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> subitems <span class="token punctuation">:</span> <span class="token punctuation">[</span> item <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NSCollectionLayoutSection</span> <span class="token punctuation">(</span> group <span class="token punctuation">:</span> group <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- To optimize the above code we will use
NSCollectionLayoutSection
to get the section index in theInt
format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeCollectionViewLayout</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewLayout</span> <span class="token punctuation">{</span> <span class="token builtin">UICollectionViewCompositionalLayout</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span> <span class="token keyword">weak</span> <span class="token keyword">self</span> <span class="token punctuation">]</span> sectionIndex <span class="token punctuation">,</span> <span class="token number">_</span> <span class="token keyword">in</span> <span class="token keyword">switch</span> <span class="token function">Section</span> <span class="token punctuation">(</span> rawValue <span class="token punctuation">:</span> sectionIndex <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span> featured <span class="token punctuation">,</span> <span class="token punctuation">.</span> onSale <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token keyword">self</span> <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token function">makeGridLayoutSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span> all <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token keyword">self</span> <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token function">makeListLayoutSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token constant">nil</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The last thing we need to do is
inject
the above code every time thecollectionView
is initialized:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeCollectionView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">{</span> <span class="token function">UICollectionView</span> <span class="token punctuation">(</span> frame <span class="token punctuation">:</span> <span class="token punctuation">.</span> zero <span class="token punctuation">,</span> collectionViewLayout <span class="token punctuation">:</span> <span class="token function">makeCollectionViewLayout</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
4: List views and content configurations:
- In
iOS14
we can completely buildtable view
usingUICollectionView
. To render sections we can simply use the previouslist
definitions instead of creating our own:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeCollectionViewLayout</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewLayout</span> <span class="token punctuation">{</span> <span class="token builtin">UICollectionViewCompositionalLayout</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span> <span class="token keyword">weak</span> <span class="token keyword">self</span> <span class="token punctuation">]</span> sectionIndex <span class="token punctuation">,</span> environment <span class="token keyword">in</span> <span class="token keyword">switch</span> <span class="token function">Section</span> <span class="token punctuation">(</span> rawValue <span class="token punctuation">:</span> sectionIndex <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span> featured <span class="token punctuation">,</span> <span class="token punctuation">.</span> onSale <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token keyword">self</span> <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token function">makeGridLayoutSection</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span> all <span class="token punctuation">:</span> <span class="token comment">// Creating our table view-like list layout using</span> <span class="token comment">// a given appearence. Here we simply use 'plain':</span> <span class="token keyword">return</span> <span class="token punctuation">.</span> <span class="token function">list</span> <span class="token punctuation">(</span> using <span class="token punctuation">:</span> <span class="token function">UICollectionLayoutListConfiguration</span> <span class="token punctuation">(</span> appearance <span class="token punctuation">:</span> <span class="token punctuation">.</span> plain <span class="token punctuation">)</span> <span class="token punctuation">,</span> layoutEnvironment <span class="token punctuation">:</span> environment <span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token constant">nil</span> <span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The above code is quite optimized, we do not need to write
custom layout
code anymore, just reuseinsetGroup
to get the desiredlayout
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">makeCollectionView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> layout <span class="token operator">=</span> <span class="token builtin">UICollectionViewCompositionalLayout</span> <span class="token punctuation">.</span> <span class="token function">list</span> <span class="token punctuation">(</span> using <span class="token punctuation">:</span> <span class="token function">UICollectionLayoutListConfiguration</span> <span class="token punctuation">(</span> appearance <span class="token punctuation">:</span> <span class="token punctuation">.</span> insetGrouped <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">UICollectionView</span> <span class="token punctuation">(</span> frame <span class="token punctuation">:</span> <span class="token punctuation">.</span> zero <span class="token punctuation">,</span> collectionViewLayout <span class="token punctuation">:</span> layout <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- We can also create and use the type
type
`UICollectionViewListCellcopy
fromUITableViewCell
so we can rendertext
,image
as well asaccesories
asindicator
.makeCellRegistration
method can be customized for us to use as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">private</span> <span class="token keyword">extension</span> <span class="token builtin">ProductListViewController</span> <span class="token punctuation">{</span> <span class="token keyword">typealias</span> <span class="token builtin">Cell</span> <span class="token operator">=</span> <span class="token builtin">UICollectionViewListCell</span> <span class="token keyword">typealias</span> <span class="token builtin">CellRegistration</span> <span class="token operator">=</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">.</span> <span class="token builtin">CellRegistration</span> <span class="token operator"><</span> <span class="token builtin">Cell</span> <span class="token punctuation">,</span> <span class="token builtin">Product</span> <span class="token operator">></span> <span class="token keyword">func</span> <span class="token function">makeCellRegistration</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">CellRegistration</span> <span class="token punctuation">{</span> <span class="token builtin">CellRegistration</span> <span class="token punctuation">{</span> cell <span class="token punctuation">,</span> indexPath <span class="token punctuation">,</span> product <span class="token keyword">in</span> <span class="token keyword">var</span> config <span class="token operator">=</span> cell <span class="token punctuation">.</span> <span class="token function">defaultContentConfiguration</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> config <span class="token punctuation">.</span> text <span class="token operator">=</span> product <span class="token punctuation">.</span> name <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> cell <span class="token punctuation">.</span> contentConfiguration <span class="token operator">=</span> config cell <span class="token punctuation">.</span> accessories <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">.</span> <span class="token function">disclosureIndicator</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |