-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
391 lines (308 loc) · 39.6 KB
/
atom.xml
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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Tim Ross]]></title>
<link href="http://timrossinfo.github.com/atom.xml" rel="self"/>
<link href="http://timrossinfo.github.com/"/>
<updated>2017-01-10T19:49:58+13:00</updated>
<id>http://timrossinfo.github.com/</id>
<author>
<name><![CDATA[Tim Ross]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Managers vs Controllers]]></title>
<link href="http://timrossinfo.github.com/blog/2013/07/03/managers-vs-controllers/"/>
<updated>2013-07-03T15:10:00+12:00</updated>
<id>http://timrossinfo.github.com/blog/2013/07/03/managers-vs-controllers</id>
<content type="html"><![CDATA[<p>A conversation on Twitter last week got me thinking about how I name my classes, particularly the difference between a Manager and a Controller class.</p>
<p>For me, a Manager is the go-to-guy for a particular aspect of functionality or data. For example, a <code>FileManager</code> handles anything related to accessing the file system. A Manager class contains only class methods, or is implemented as a <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a>, as no separate instances are usually required.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[</span><span class="n">MyFileManager</span> <span class="nl">fileExistsAtPath:</span><span class="n">myPath</span><span class="p">];</span> <span class="c1">// Class method</span>
</span></code></pre></td></tr></table></div></figure>
<p>or</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[[</span><span class="n">MyFileManager</span> <span class="n">sharedManager</span><span class="p">]</span> <span class="nl">fileExistsAtPath:</span><span class="n">myPath</span><span class="p">];</span> <span class="c1">// Singleton</span>
</span></code></pre></td></tr></table></div></figure>
<p>A Controller class co-ordinates a process. For example, a <code>PurchaseController</code> controls the series of actions in purchasing a product. A <code>ViewController</code> co-ordinates a series of actions for interacting with a View.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">MyPurchaseController</span> <span class="o">*</span><span class="n">purchaseController</span> <span class="o">=</span> <span class="p">[[</span><span class="n">MyPurchaseController</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithDelegate:</span><span class="n">self</span><span class="p">];</span>
</span><span class='line'><span class="p">[</span><span class="n">purchaseController</span> <span class="nl">purchaseProduct:</span><span class="n">productId</span><span class="p">];</span> <span class="c1">// Begins purchase process</span>
</span><span class='line'><span class="p">...</span>
</span><span class='line'><span class="p">[</span><span class="n">purchaseController</span> <span class="n">cancelPurchase</span><span class="p">];</span> <span class="c1">// Cancels process</span>
</span></code></pre></td></tr></table></div></figure>
<p>Everyone has their own naming preferences, and yours might be different. It’s not really the names themselves that’s important, but that the naming is consistent throughout the application. Remember, it’s all about communicating intent to yourself and others who use your code.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[More Fun With UIAppearance]]></title>
<link href="http://timrossinfo.github.com/blog/2013/03/26/more-fun-with-uiappearance/"/>
<updated>2013-03-26T20:14:00+13:00</updated>
<id>http://timrossinfo.github.com/blog/2013/03/26/more-fun-with-uiappearance</id>
<content type="html"><![CDATA[<p>In <a href="http://timrossinfo.github.com/blog/2013/03/26/uiappearance-with-uiss">my last post</a> I discussed using UIAppearance with <a href="http://github.com/robertwijas/UISS">UISS</a> to style iOS apps. Today I discovered a few more tricks with UIAppearance.</p>
<p>UIKit only exposes a limited set of elements that can be styled with UIAppearance. But what if we want to style something that’s not exposed? Well, it turns out you can define your own UIAppearance proxies by appending a setter method declaration with <code>UI_APPEARANCE_SELECTOR</code>.</p>
<p>Say, for example, I want to use UIAppearance to set rounded corners on a UIView. I can create a <code>setCornerRadius</code> method on a UIView subclass that’s appended with <code>UI_APPEARANCE_SELECTOR</code>:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@interface</span> <span class="nc">MyView</span> : <span class="nc">UIView</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setCornerRadius:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">cornerRadius</span> <span class="n">UI_APPEARANCE_SELECTOR</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>
<p>UIView itself doesn’t have a <code>corderRadius</code> property, so the implementation needs to set the value on the underlying CALayer:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@implementation</span> <span class="nc">MyView</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setCornerRadius:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">cornerRadius</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">layer</span><span class="p">.</span><span class="n">cornerRadius</span> <span class="o">=</span> <span class="n">cornerRadius</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now I can set the new <code>corderRadius</code> style on all instances of <code>MyView</code> with UIAppearance:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[[</span><span class="n">MyView</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setCornerRadius:</span><span class="mi">3</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>
<p>Or, with <a href="http://github.com/robertwijas/UISS">UISS</a> I can use JSON to set the style:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"MyView"</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"cornerRadius"</span><span class="o">:</span> <span class="mi">3</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now, this is pretty neat, but what if I want to expose <code>cornerRadius</code> on every UIView in the application, not just the subclass? Well, it turns out you can create a category on UIView that defines custom UIAppearance methods:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@interface</span> <span class="nc">UIView</span> <span class="nl">(Appearance)</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setCornerRadius:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">cornerRadius</span> <span class="n">UI_APPEARANCE_SELECTOR</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setBorderColor:</span><span class="p">(</span><span class="n">UIColor</span> <span class="o">*</span><span class="p">)</span><span class="nv">borderColor</span> <span class="n">UI_APPEARANCE_SELECTOR</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setBorderWidth:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">borderWidth</span> <span class="n">UI_APPEARANCE_SELECTOR</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span><span class='line'>
</span><span class='line'><span class="k">@implementation</span> <span class="nc">UIView</span> <span class="nl">(Appearance)</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setCornerRadius:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">cornerRadius</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">layer</span><span class="p">.</span><span class="n">cornerRadius</span> <span class="o">=</span> <span class="n">cornerRadius</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setBorderColor:</span><span class="p">(</span><span class="n">UIColor</span> <span class="o">*</span><span class="p">)</span><span class="nv">borderColor</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">layer</span><span class="p">.</span><span class="n">borderColor</span> <span class="o">=</span> <span class="n">borderColor</span><span class="p">.</span><span class="n">CGColor</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setBorderWidth:</span><span class="p">(</span><span class="n">CGFloat</span><span class="p">)</span><span class="nv">borderWidth</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">layer</span><span class="p">.</span><span class="n">borderWidth</span> <span class="o">=</span> <span class="n">borderWidth</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>
<p>So now every UIView in the application can have the <code>cornerRadius</code>, <code>borderColor</code> and <code>borderWidth</code> elements styled:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"UIView"</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"cornerRadius"</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"borderColor"</span><span class="o">:</span> <span class="p">[</span><span class="mi">26</span><span class="p">,</span> <span class="mi">26</span><span class="p">,</span> <span class="mi">26</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"borderWidth"</span><span class="o">:</span> <span class="mi">1</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Custom UIAppearance methods enable more elements to be exposed for styling. <a href="http://github.com/robertwijas/UISS">UISS</a> makes this code more readable by allowing styles to be defined using JSON.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Improving Readability of UIAppearance Code With UISS]]></title>
<link href="http://timrossinfo.github.com/blog/2013/03/26/uiappearance-with-uiss/"/>
<updated>2013-03-26T10:14:00+13:00</updated>
<id>http://timrossinfo.github.com/blog/2013/03/26/uiappearance-with-uiss</id>
<content type="html"><![CDATA[<p><a href="http://useyourloaf.com/blog/2012/08/24/using-appearance-proxy-to-style-apps.html">UIAppearance</a> is a convenient way to define styles for UIKit classes throughout your application. For example, instead of setting the font on every UILabel, you can define it once using a UIAppearance proxy:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[[</span><span class="n">UILabel</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setFont:</span><span class="p">[</span><span class="n">UIFont</span> <span class="nl">fontWithName:</span><span class="s">@"Avenir-Medium"</span> <span class="nl">size:</span><span class="mi">11</span><span class="p">]];</span>
</span></code></pre></td></tr></table></div></figure>
<p>Of course this is Objective-C, so the UIAppearance code is verbose and can be quite difficult to read. If you work with a designer who might like to tweak these values, the code can appear daunting. Luckily there’s a quick and simple way to make UIAppearance code easier to read (and write!).</p>
<h2>Introducing UISS</h2>
<p><a href="http://github.com/robertwijas/UISS">UISS</a>, developed by <a href="http://robertwijas.com">Robert Wijas</a>, is an iOS library build on top of UIAppearance that provides a convenient way to define styles using JSON.</p>
<p>Let’s look at a more complex example of styles defined in Objective-C using UIAppearance:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[[</span><span class="n">UIButton</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setTitleColor:</span><span class="p">[</span><span class="n">UIColor</span> <span class="nl">colorWithRed:</span><span class="mf">204.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">green:</span><span class="mf">204.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">blue:</span><span class="mf">204.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">alpha:</span><span class="mi">1</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UIButton</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setTitleColor:</span><span class="p">[</span><span class="n">UIColor</span> <span class="nl">colorWithRed:</span><span class="mf">160.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">green:</span><span class="mf">160.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">blue:</span><span class="mf">160.f</span><span class="o">/</span><span class="mf">255.f</span> <span class="nl">alpha:</span><span class="mi">1</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateHighlighted</span><span class="p">];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UIButton</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setTitleShadowColor:</span><span class="p">[</span><span class="n">UIColor</span> <span class="nl">colorWithWhite:</span><span class="mi">0</span> <span class="nl">alpha:</span><span class="mf">0.7</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UIButton</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setBackgroundImage:</span><span class="p">[[</span><span class="n">UIImage</span> <span class="nl">imageNamed:</span><span class="s">@"ButtonGrey"</span><span class="p">]</span> <span class="nl">resizableImageWithCapInsets:</span><span class="n">UIEdgeInsetsMake</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UIButton</span> <span class="n">appearance</span><span class="p">]</span> <span class="nl">setBackgroundImage:</span><span class="p">[[</span><span class="n">UIImage</span> <span class="nl">imageNamed:</span><span class="s">@"ButtonGreyTap"</span><span class="p">]</span> <span class="nl">resizableImageWithCapInsets:</span><span class="n">UIEdgeInsetsMake</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span> <span class="nl">forState:</span><span class="n">UIControlStateHighlighted</span><span class="p">];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UILabel</span> <span class="nl">appearanceWhenContainedIn:</span><span class="p">[</span><span class="n">UIButton</span> <span class="n">class</span><span class="p">],</span> <span class="nb">nil</span><span class="p">]</span> <span class="nl">setFont:</span><span class="p">[</span><span class="n">UIFont</span> <span class="nl">fontWithName:</span><span class="s">@"Avenir-Medium"</span> <span class="nl">size:</span><span class="mi">11</span><span class="p">]];</span>
</span><span class='line'><span class="p">[[</span><span class="n">UILabel</span> <span class="nl">appearanceWhenContainedIn:</span><span class="p">[</span><span class="n">UIButton</span> <span class="n">class</span><span class="p">],</span> <span class="nb">nil</span><span class="p">]</span> <span class="nl">setShadowOffset:</span><span class="n">CGSizeMake</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)];</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now here’s the equivalent styles defined in JSON using UISS:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"UIButton"</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"titleColor:normal"</span><span class="o">:</span> <span class="p">[</span><span class="mi">204</span><span class="p">,</span> <span class="mi">204</span><span class="p">,</span> <span class="mi">204</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"titleColor:highlighted"</span><span class="o">:</span> <span class="p">[</span><span class="mi">160</span><span class="p">,</span> <span class="mi">160</span><span class="p">,</span> <span class="mi">160</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"titleShadowColor:normal"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"black"</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"backgroundImage:normal"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"ButtonGrey"</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"backgroundImage:highlighted"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"ButtonGreyTap"</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"UILabel"</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"font"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"Avenir-Medium"</span><span class="p">,</span> <span class="mi">11</span><span class="p">],</span>
</span><span class='line'> <span class="s2">"shadowOffset"</span><span class="o">:</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>The UISS code is not only easier to read, but also more pleasurable to write!</p>
<p>UISS includes logging and a console for troubleshooting style problems. It can even generate the equivalent UIAppearance code from the JSON files, which is handy if you want to see exactly what’s going on.</p>
<p>Styles can even be loaded from a remote server to enable live style updates in your app.</p>
<p>I was able to get up and running with UISS quickly and found it greatly improved the readability of my UIAppearance definitions. UISS is available on <a href="http://github.com/robertwijas/UISS">GitHub</a> or as a <a href="http://cocoapods.org/?q=uiss">Cocoapod</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[To Segue or Not to Segue]]></title>
<link href="http://timrossinfo.github.com/blog/2013/03/19/to-segue-or-not-to-segue/"/>
<updated>2013-03-19T10:38:00+13:00</updated>
<id>http://timrossinfo.github.com/blog/2013/03/19/to-segue-or-not-to-segue</id>
<content type="html"><![CDATA[<p>iOS 5 introduced <a href="http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1">Storyboards</a>, which allow you to visually define the flow of an app. The transitions between view controllers in a Storyboard are called “Segues”.</p>
<p>Initially, the benefits of using segues seem clear:</p>
<ul>
<li>Spend less time writing boring transition code.</li>
<li>Code is cleaner and not littered with transitions.</li>
<li>You get a visual representation of how the app fits together.</li>
</ul>
<p>However, after using segues for a while I’ve found there are a few downsides:</p>
<ul>
<li>The visual layout is restricted. Segues always exit from right of a controller and enter from the left. For any moderately complex app, you can end up with a storyboard that resembles spaghetti.</li>
<li>I almost always need to pass data to the controller I’m transitioning to. This requires dropping back to the code to intercept the segue, find the controller, then set its properties.</li>
<li>I often find I end up writing quite lengthy and obscure code to intercept the segue.</li>
</ul>
<p>Here’s a comparison of transitioning using segues versus a traditional approach. In this code I’m handling tapping a detail accessory on a row in a table view, then transitioning to a view controller.</p>
<p>First, I’ll use a segue:</p>
<p><img src="http://timrossinfo.github.com/images/segue1.png" width="789"></p>
<p>In theory I should just be able to connect a segue from the detail accessory to the next view controller and I’m done! Not quite… I also need to assign some data on the controller I’m transitioning to. So I need to intercept the segue by implementing the <code>prepareForSegue</code> method, then check the segue identifier to ensure I am handling the correct segue:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">prepareForSegue:</span><span class="p">(</span><span class="n">UIStoryboardSegue</span> <span class="o">*</span><span class="p">)</span><span class="nv">segue</span> <span class="nf">sender:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">([</span><span class="n">segue</span><span class="p">.</span><span class="n">identifier</span> <span class="nl">isEqualToString:</span><span class="s">@"ContactDetailSegue"</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'> <span class="n">ContactDetailViewController</span> <span class="o">*</span><span class="n">controller</span> <span class="o">=</span> <span class="n">segue</span><span class="p">.</span><span class="n">destinationViewController</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>So I have the controller and now I need to assign some data to it. But how do I know which row was tapped? There is nothing in UITableView that stores the selected state for an accessory view. So I’ll need an instance variable to store the row index and set this in the <code>tableView:accessoryButtonTappedForRowWithIndexPath:</code> method:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">tableView:</span><span class="p">(</span><span class="n">UITableView</span> <span class="o">*</span><span class="p">)</span><span class="nv">tableView</span> <span class="nf">accessoryButtonTappedForRowWithIndexPath:</span><span class="p">(</span><span class="n">NSIndexPath</span> <span class="o">*</span><span class="p">)</span><span class="nv">indexPath</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">selectedDetailIndexPath</span> <span class="o">=</span> <span class="n">indexPath</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now I can use this to assign data to the controller I am transitioning to:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">prepareForSegue:</span><span class="p">(</span><span class="n">UIStoryboardSegue</span> <span class="o">*</span><span class="p">)</span><span class="nv">segue</span> <span class="nf">sender:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">([</span><span class="n">segue</span><span class="p">.</span><span class="n">identifier</span> <span class="nl">isEqualToString:</span><span class="s">@"ContactDetailSegue"</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'> <span class="n">ContactDetailViewController</span> <span class="o">*</span><span class="n">controller</span> <span class="o">=</span> <span class="n">segue</span><span class="p">.</span><span class="n">destinationViewController</span><span class="p">;</span>
</span><span class='line'> <span class="n">Contact</span> <span class="o">*</span><span class="n">contact</span> <span class="o">=</span> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">contacts</span> <span class="nl">objectAtIndex:</span><span class="n">self</span><span class="p">.</span><span class="n">selectedDetailIndexPath</span><span class="p">.</span><span class="n">row</span><span class="p">];</span>
</span><span class='line'> <span class="n">controller</span><span class="p">.</span><span class="n">contact</span> <span class="o">=</span> <span class="n">contact</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>But hang on! The <code>tableView:accessoryButtonTappedForRowWithIndexPath:</code> method gets called <em>after</em> <code>prepareForSegue</code>, which means my <code>selectedDetailIndexPath</code> variable is not yet set. So now I need to disconnect the automatic segue from the detail accessory and instead create a <em>manual</em> segue between the two controllers.</p>
<p><img src="http://timrossinfo.github.com/images/segue2.png" width="789"></p>
<p>Next, I need to call <code>performSegueWithIdentifier</code> to manually trigger the segue in the <code>tableView:accessoryButtonTappedForRowWithIndexPath:</code> method</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">tableView:</span><span class="p">(</span><span class="n">UITableView</span> <span class="o">*</span><span class="p">)</span><span class="nv">tableView</span> <span class="nf">accessoryButtonTappedForRowWithIndexPath:</span><span class="p">(</span><span class="n">NSIndexPath</span> <span class="o">*</span><span class="p">)</span><span class="nv">indexPath</span> <span class="p">{</span>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">selectedDetailIndexPath</span> <span class="o">=</span> <span class="n">indexPath</span><span class="p">;</span>
</span><span class='line'> <span class="p">[</span><span class="n">self</span> <span class="nl">performSegueWithIdentifier:</span><span class="s">@"ContactDetailSegue"</span> <span class="nl">sender:</span><span class="n">self</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Phew, that ended up being quite complicated.</p>
<p>Now, let’s look at the “traditional” way of coding a transition without segues using <code>pushViewController</code>:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">tableView:</span><span class="p">(</span><span class="n">UITableView</span> <span class="o">*</span><span class="p">)</span><span class="nv">tableView</span> <span class="nf">accessoryButtonTappedForRowWithIndexPath:</span><span class="p">(</span><span class="n">NSIndexPath</span> <span class="o">*</span><span class="p">)</span><span class="nv">indexPath</span> <span class="p">{</span>
</span><span class='line'> <span class="n">ContactDetailViewController</span> <span class="o">*</span><span class="n">controller</span> <span class="o">=</span> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">storyboard</span> <span class="nl">instantiateViewControllerWithIdentifier:</span><span class="s">@"ContactDetailViewController"</span><span class="p">];</span>
</span><span class='line'> <span class="n">Contact</span> <span class="o">*</span><span class="n">contact</span> <span class="o">=</span> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">contacts</span> <span class="nl">objectAtIndex:</span><span class="n">indexPath</span><span class="p">.</span><span class="n">row</span><span class="p">];</span>
</span><span class='line'> <span class="n">controller</span><span class="p">.</span><span class="n">contact</span> <span class="o">=</span> <span class="n">contact</span><span class="p">;</span>
</span><span class='line'> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">navigationController</span> <span class="nl">pushViewController:</span><span class="n">controller</span> <span class="nl">animated:</span><span class="n">YES</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>That replaces all the previous code! Feels much simpler, doesn’t it? What I like about this is that the transition code is all in one place, not spread across two methods. Sure, there’s no “visual” representation of the transition, but if the code is clean and clear, it should be easy to determine how one controller transitions to the next.</p>
<p>So should you ditch using segues? Not necessarily. They can definitely save time if you are transitioning between static views. But there may be cases where it’s cleaner and simpler to do a manual transition rather than use a segue.</p>
<p>Segues are a step in the right direction, the less code we have to write the better! Hopefully they’ll continue to be improved in future updates of iOS. But with the current implementation, you often have to write quite obscure code to work-around the limitations.</p>
]]></content>
</entry>
</feed>