-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathresults-controller.html
More file actions
363 lines (330 loc) · 24.1 KB
/
results-controller.html
File metadata and controls
363 lines (330 loc) · 24.1 KB
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
<!DOCTYPE html>
<html lang="en">
<head>
<title>Results Controller Reference</title>
<link rel="stylesheet" type="text/css" href="css/jazzy.css" />
<link rel="stylesheet" type="text/css" href="css/highlight.css" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1.0" />
<script src="js/jquery.min.js" defer></script>
<script src="js/jazzy.js" defer></script>
</head>
<body>
<a title="Results Controller Reference"></a>
<header>
<div class="content-wrapper">
<p>
<a href="index.html">CollectionView Docs</a>
<span class="no-mobile"> (63% documented)</span>
</p>
<p class="header-right">
<a href="https://github.com/TheNounProject/CollectionView">
<img src="img/gh.png"/>
<span class="no-mobile">View on GitHub</span>
</a>
</p>
</div>
</header>
<div id="breadcrumbs-container">
<div class="content-wrapper">
<p id="breadcrumbs">
<span class="no-mobile">
<a href="index.html">CollectionView Reference</a>
<img id="carat" src="img/carat.png" />
</span>
Results Controller Reference
</p>
</div>
</div>
<div class="wrapper">
<div class="article-wrapper">
<article class="main-content">
<section>
<section class="section">
<h1 id='results-controller' class='heading'>Results Controller</h1>
<p>Collection views are a data driven UI element. Managing data is hard enough, making sure changes to that data are relfected in your app can add a lot of complexity quickly; Especially with highly dynamic data.</p>
<p><code>Resultscontroller</code> is designed to bridge the gap between data and a collection view. While its inspiration, NSFetchedResultsController only works with CoreData and its NSManagedObject, this implementation uses native Swift KeyPaths and a generic SortDescriptor type making usable any object type.</p>
<hr>
<h2 id='a-mutable-results-controller' class='heading'>A Mutable Results Controller?</h2>
<p>Traditionally, the beauty of NSFetchedResutls controller is that it listens to your Core Data store and tells you when changes are made. This is great, and you can do that here too (see below) but one of the other helpful aspects of a results controller is translating changes in your data to changes in a collection view. As mentioned in the Content Manipulation guide, tracking those changes can complicated with highly dynamic data.</p>
<p>MutableResultsController is designed manage your data, respond to changes in that data, and translate those changes into updates a collection view can understand. The only difference from a core data backed controller that recieves changes by monitoring the store is that you provide the changes. Let’s take a look</p>
<p>A very basic example of a mutable results controller setup:</p>
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">mrc</span> <span class="o">=</span> <span class="kt">MutableResultsController</span><span class="o"><</span><span class="kt">NoSectionType</span><span class="p">,</span> <span class="kt">Child</span><span class="o">></span><span class="p">()</span>
<span class="k">let</span> <span class="nv">child1</span> <span class="o">=</span> <span class="kt">Child</span><span class="p">()</span>
<span class="k">let</span> <span class="nv">child2</span> <span class="o">=</span> <span class="kt">Child</span><span class="p">()</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">setContents</span><span class="p">([</span><span class="n">child1</span><span class="p">,</span> <span class="n">child2</span><span class="p">])</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfSections</span><span class="p">()</span> <span class="c1">// 1</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfObjects</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">// 2</span>
</code></pre>
<p>In this simple example we it may not seem clear why using a controller is better than a simple array. One nice benefit is that you can maintain a consistent api for powering your data source. But the real power comes when we start set up a more complex controller.</p>
<p>Let’s add a section key path and ordering. Defining a name and age property on our Child object we can then use those properties to group and sort a set of chilren. Let’s group them by age and then sort by name within each group. And finally we also went each group to line up from youngest to oldes.</p>
<pre class="highlight swift"><code><span class="kd">struct</span> <span class="kt">Child</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">name</span> <span class="p">:</span> <span class="kt">String</span>
<span class="k">let</span> <span class="nv">age</span> <span class="p">:</span> <span class="kt">String</span>
<span class="p">}</span>
<span class="k">let</span> <span class="nv">mrc</span> <span class="o">=</span> <span class="kt">MutableResultsController</span><span class="o"><</span><span class="kt">Int</span><span class="p">,</span> <span class="kt">Child</span><span class="o">></span><span class="p">(</span><span class="nv">sectionKeyPath</span><span class="p">:</span> <span class="p">\</span><span class="kt">Child</span><span class="o">.</span><span class="n">rank</span><span class="p">,</span>
<span class="nv">sortDescriptors</span><span class="p">:</span> <span class="p">[</span><span class="kt">SortDescriptor</span><span class="p">(\</span><span class="kt">Child</span><span class="o">.</span><span class="n">name</span><span class="p">)],</span>
<span class="nv">sectionSortDescriptors</span><span class="p">:</span> <span class="p">[</span><span class="kt">SortDescriptor</span><span class="o"><</span><span class="kt">Int</span><span class="o">>.</span><span class="n">ascending</span><span class="p">])</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">setContents</span><span class="p">([</span>
<span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Geoff"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">9</span><span class="p">),</span>
<span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Sarah"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">8</span><span class="p">),</span>
<span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Steve"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">10</span><span class="p">)</span>
<span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Amy"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">8</span><span class="p">),</span>
<span class="p">])</span>
<span class="c1">// Sections</span>
<span class="mi">8</span> <span class="p">:</span> <span class="p">[</span><span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Amy"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">8</span><span class="p">),</span> <span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Sarah"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">8</span><span class="p">)]</span>
<span class="mi">9</span> <span class="p">:</span> <span class="p">[</span><span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Geoff"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">9</span><span class="p">)]</span>
<span class="mi">10</span><span class="p">:</span> <span class="p">[</span><span class="kt">Child</span><span class="p">((</span><span class="nv">name</span><span class="p">:</span> <span class="s">"Steve"</span><span class="p">,</span> <span class="nv">age</span><span class="p">:</span> <span class="mi">10</span><span class="p">)]</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfSections</span><span class="p">()</span> <span class="c1">// 3</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfObjects</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">// 2</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfObjects</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">// 1</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">numberOfObjects</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="mi">2</span><span class="p">)</span> <span class="c1">// 1</span>
<span class="n">mrc</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">at</span><span class="p">:</span> <span class="kt">IndexPath</span><span class="o">.</span><span class="k">for</span><span class="p">(</span><span class="nv">item</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">section</span><span class="p">:</span> <span class="mi">0</span><span class="p">))</span> <span class="c1">// name:Amy age:8)</span>
</code></pre>
<p>Using results controller now provides a bit more usfullness. Setting the contents handles a lot of data processing both grouping the items then sorting everything, that data is then exposed in a consistent API that aligns with the collection view API. When implementing collections views in various places results controller can help make more of your collection view implmentations reusable.</p>
<h4 id='updating-data' class='heading'>Updating Data</h4>
<p>Of course as a <q>mutable</q> results controller, data can be mutated when working with elements of a reference type.</p>
<p>To insert or delete items just call <code>insert(object:)</code> or <code>delete(object:)</code>. To update objects that already exist, make the changes to your object then call <code>didUpdate(object:</code>. For a controller with a sectionKeyPath and/or sort descriptors, notifying it of the change will alert the controller to process that change and update its internal storage.</p>
<h3 id='delegate' class='heading'>Delegate</h3>
<p>So far results controller has provided a simple consistent interface and helpful sorting and grouping, why is this in a collection view library you ask? Typically when you insert, remove, or update data in your data set you first need to determine <em>how</em> that updates our data set. Then you need to translate that into terms the collection view understands to reflect those changes on the screen. By letting results controller manage your data, it will make those translations and provide them to its delegate which conforms to <code><a href="Protocols/ResultsControllerDelegate.html">ResultsControllerDelegate</a></code>.</p>
<p>The delegate will recieve every change that needs to occur in your collection view to keep it up to date with your data set.</p>
<h2 id='collection-view-provider' class='heading'>Collection View Provider</h2>
<p><code><a href="Classes/CollectionViewProvider.html">CollectionViewProvider</a></code> is a helper object that automatically handles the connection between your results controller and a collection view. It holds a references to both objects, becomes the results controllers delegate and automatically pushes changes to the collection view.</p>
<p>After setting up a provider the <em>only</em> steps left up to you are:</p>
<ol>
<li>load and set your data</li>
<li>Make a change in your data</li>
<li>Tell the results controller</li>
</ol>
<p>The provider will coordinate the everything else.</p>
<p>Compare that to the steps in a traditional:</p>
<ol>
<li>Design a data structure</li>
<li>Load your data</li>
<li>Sort and group the data as needed</li>
<li>Reload data</li>
<li>Change and object</li>
<li>Resort and regroup the data</li>
<li>Translate the change into collection view updates</li>
<li>Dispatch those updates</li>
</ol>
<h2 id='core-data-results-controllers' class='heading'>Core Data Results Controllers</h2>
<p>Mentioned above, Results Controller is inspired by NSFetchedResultsController and originally started as a CoreData only controller. As of v2 of CollectionView though the core data implementation is a simple subclass of MutableResultsController.</p>
<p><code><a href="Classes/FetchedResultsController.html">FetchedResultsController</a></code> and <code><a href="Classes/RelationalResultsController.html">RelationalResultsController</a></code> monitor the provided NSManagedObjectContext for changes and process those changes, updating their data as needed.</p>
<p>See the docs for these controllers for more information.</p>
</section>
</section>
</article>
</div>
<div class="nav-wrapper">
<nav class="nav-bottom">
<ul class="nav-groups">
<li class="nav-group-name">
<a href="Guides.html">Guides</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="introduction.html">Introduction</a>
</li>
<li class="nav-group-task">
<a href="basic-setup.html">Basic Setup</a>
</li>
<li class="nav-group-task">
<a href="supplementary-views.html">Supplementary Views</a>
</li>
<li class="nav-group-task">
<a href="layouts.html">Layouts</a>
</li>
<li class="nav-group-task">
<a href="drag--drop.html">Drag & Drop</a>
</li>
<li class="nav-group-task">
<a href="content-updates.html">Content Updates</a>
</li>
<li class="nav-group-task">
<a href="results-controller.html">Results Controller</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Collection View.html">Collection View</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Classes/CollectionView.html">CollectionView</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionView.html#/s:14CollectionViewAAC13SelectionModeO">– SelectionMode</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDataSource.html">CollectionViewDataSource</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDelegate.html">CollectionViewDelegate</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDragDelegate.html">CollectionViewDragDelegate</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewCell.html">CollectionViewCell</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionReusableView.html">CollectionReusableView</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewController.html">CollectionViewController</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView0aB17LayoutElementKindV">CollectionViewLayoutElementKind</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView0A15ElementCategoryO">CollectionElementCategory</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView0aB9DirectionO">CollectionViewDirection</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView0aB15ScrollDirectionO">CollectionViewScrollDirection</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView0aB14ScrollPositionO">CollectionViewScrollPosition</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewPreviewCell.html">CollectionViewPreviewCell</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewPreviewController.html">CollectionViewPreviewController</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewPreviewTransitionCell.html">CollectionViewPreviewTransitionCell</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewPreviewControllerDelegate.html">CollectionViewPreviewControllerDelegate</a>
</li>
<li class="nav-group-task">
<a href="Collection View.html#/s:14CollectionView19AnimationCompletiona">AnimationCompletion</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Collection View Layouts.html">Collection View Layouts</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Classes/CollectionViewLayout.html">CollectionViewLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewLayoutAttributes.html">CollectionViewLayoutAttributes</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewListLayout.html">CollectionViewListLayout</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDelegateListLayout.html">CollectionViewDelegateListLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewColumnLayout.html">CollectionViewColumnLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewColumnLayout.html#/s:14CollectionView0aB12ColumnLayoutC0D8StrategyO">– LayoutStrategy</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDelegateColumnLayout.html">CollectionViewDelegateColumnLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewFlowLayout.html">CollectionViewFlowLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewFlowLayout.html#/s:14CollectionView0aB10FlowLayoutC12RowTransformO">– RowTransform</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewFlowLayout/ItemStyle.html">– ItemStyle</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDelegateFlowLayout.html">CollectionViewDelegateFlowLayout</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewHorizontalListLayout.html">CollectionViewHorizontalListLayout</a>
</li>
<li class="nav-group-task">
<a href="Protocols/CollectionViewDelegateHorizontalListLayout.html">CollectionViewDelegateHorizontalListLayout</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Results Controller.html">Results Controller</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Protocols/ResultsController.html">ResultsController</a>
</li>
<li class="nav-group-task">
<a href="Protocols/ResultsControllerDelegate.html">ResultsControllerDelegate</a>
</li>
<li class="nav-group-task">
<a href="Classes/MutableResultsController.html">MutableResultsController</a>
</li>
<li class="nav-group-task">
<a href="Classes/FetchedResultsController.html">FetchedResultsController</a>
</li>
<li class="nav-group-task">
<a href="Classes/RelationalResultsController.html">RelationalResultsController</a>
</li>
<li class="nav-group-task">
<a href="Classes/FetchedSetController.html">FetchedSetController</a>
</li>
<li class="nav-group-task">
<a href="Results Controller.html#/s:14CollectionView27ResultsControllerChangeTypeO">ResultsControllerChangeType</a>
</li>
<li class="nav-group-task">
<a href="Results Controller.html#/s:14CollectionView22ResultsControllerErrorO">ResultsControllerError</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewProvider.html">CollectionViewProvider</a>
</li>
<li class="nav-group-task">
<a href="Classes/CollectionViewResultsProxy.html">CollectionViewResultsProxy</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Other Enums.html">Other Enumerations</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Enums/SortDescriptorResult.html">SortDescriptorResult</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Other Extensions.html">Other Extensions</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Extensions/IndexPath.html">IndexPath</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Other Protocols.html">Other Protocols</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Other Protocols.html#/s:14CollectionView30CustomDisplayStringConvertibleP">CustomDisplayStringConvertible</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a href="Other Structs.html">Other Structures</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Structs/SortDescriptor.html">SortDescriptor</a>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="footer-wrapper">
<section id="footer">
<p>© 2018 <a class="link" href="" target="_blank" rel="external">Noun Project</a>. All rights reserved. (Last updated: 2018-10-16)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.9.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</div>
</div>
</body>
</div>
</html>