Skip to content
Newer
Older
100644 437 lines (293 sloc) 18.9 KB
48b63af @groue ViewModel guide
authored
1 [up](../../../../GRMustache#documentation), [next](view_model.md)
1a1555f @groue guides wip
authored
2
6aa657e @groue guides wip
authored
3 GRMustache runtime
4 ==================
1a1555f @groue guides wip
authored
5
9e807c9 @groue ViewModel Guide WIP
authored
6 You'll learn here how GRMustache renders your data. The loading of templates is covered in the [Templates Guide](templates.md). Common patterns for feeding templates are described in the [ViewModel Guide](view_model.md).
e1ce058 @groue Simplify the Runtime Guide
authored
7
8 Variable tags
9 -------------
10
11 Variable tags `{{ name }}` and `{{{ name }}}` look for the `name` key in the object you provide:
cc892a6 @groue Runtime Guide clean up
authored
12
13 ```objc
e1ce058 @groue Simplify the Runtime Guide
authored
14 id data = @{ @"name": @"Arthur" };
15
16 // Renders "Hello Arthur!"
17 NSString *rendering = [GRMustacheTemplate renderObject:data
18 fromString:@"Hello {{name}}!"
19 error:NULL];
20 ```
21
3f366df @groue v6.9.0
authored
22 Any object supporting [keyed subscripting](http://clang.llvm.org/docs/ObjectiveCLiterals.html#dictionary-style-subscripting) via the `objectForKeyedSubscript:` method, and any [Key-Value Coding](http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html) compliant object, that responds to the `valueForKey:` method, can be used.
23
24 Note that GRMustache prefers the `objectForKeyedSubscript:` method, and only invokes the `valueForKey:` method on objects that do not respond to `objectForKeyedSubscript:`.
e1ce058 @groue Simplify the Runtime Guide
authored
25
26 Dictionaries are such objects. So are, generally speaking, your custom models:
cc892a6 @groue Runtime Guide clean up
authored
27
e1ce058 @groue Simplify the Runtime Guide
authored
28 ```objc
29 // The Person class defines the `name` property:
30 Person *barbara = [Person personWithName:@"Barbara"];
cc892a6 @groue Runtime Guide clean up
authored
31
e1ce058 @groue Simplify the Runtime Guide
authored
32 // Renders "Hello Barbara!"
33 NSString *rendering = [GRMustacheTemplate renderObject:barbara
34 fromString:@"Hello {{name}}!"
35 error:NULL];
cc892a6 @groue Runtime Guide clean up
authored
36 ```
37
4f170ea @groue Typos
authored
38 Remember that `{{ name }}` renders HTML-escaped values, when `{{{ name }}}` and `{{& name }}` render unescaped values.
e1ce058 @groue Simplify the Runtime Guide
authored
39
3f366df @groue v6.9.0
authored
40 Values are usually rendered with the [standard](http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html) `description` method, with two exceptions:
cc892a6 @groue Runtime Guide clean up
authored
41
e833258 @groue Wording
authored
42 - Your custom objects that take full charge of their own rendering. See the [Rendering Objects Guide](rendering_objects.md) for further details.
7e94c24 @groue Wording
authored
43 - Objects conforming to the [NSFastEnumeration](http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocFastEnumeration.html) protocol (but NSDictionary):
cc892a6 @groue Runtime Guide clean up
authored
44
7e94c24 @groue Wording
authored
45 A variable tag renders all items of enumerable objects:
e1ce058 @groue Simplify the Runtime Guide
authored
46
47 ```objc
48 id data = @{ @"voyels": @[@"A", @"E", @"I", @"O", @"U"] };
cc892a6 @groue Runtime Guide clean up
authored
49
e1ce058 @groue Simplify the Runtime Guide
authored
50 // Renders "AEIOU"
51 NSString *rendering = [GRMustacheTemplate renderObject:data
52 fromString:@"{{voyels}}"
53 error:NULL];
54 ```
cc892a6 @groue Runtime Guide clean up
authored
55
4f170ea @groue Typos
authored
56 This especially comes handy with your custom [rendering objects](rendering_objects.md): you may think of Ruby on Rails' `<%= render @items %>`.
57
e1ce058 @groue Simplify the Runtime Guide
authored
58 Expressions
59 -----------
cc892a6 @groue Runtime Guide clean up
authored
60
e1ce058 @groue Simplify the Runtime Guide
authored
61 Variable tags render simple keys as seen above, and, more generally, *expressions*, such as the key path `person.name` and the filtered expression `uppercase(person.name)`.
cc892a6 @groue Runtime Guide clean up
authored
62
e1ce058 @groue Simplify the Runtime Guide
authored
63 ```objc
64 Person *craig = [Person personWithName:@"Craig"];
65 id data = @{ @"person": craig };
cc892a6 @groue Runtime Guide clean up
authored
66
e1ce058 @groue Simplify the Runtime Guide
authored
67 // Renders "Hello CRAIG!"
68 NSString *rendering = [GRMustacheTemplate renderObject:data
69 fromString:@"Hello {{ uppercase(person.name) }}!"
70 error:NULL];
71 ```
cc892a6 @groue Runtime Guide clean up
authored
72
9e10d6c @groue Guides WIP
authored
73 GRMustache first looks for the `person` key, extracts its `name`, and applies the `uppercase` built-in filter of the [standard library](standard_library.md). The variable tag eventually renders the resulting string.
1a1555f @groue guides wip
authored
74
75
e1ce058 @groue Simplify the Runtime Guide
authored
76 Section tags
77 ------------
1a1555f @groue guides wip
authored
78
e1ce058 @groue Simplify the Runtime Guide
authored
79 The rendering of section tags such as `{{# name }}...{{/ name }}` and `{{^ name }}...{{/ name }}` depend on the value attached to the `name` expression.
80
b9bec57 @groue Wording
authored
81 Generally speaking, *inverted sections* `{{^ name }}...{{/ name }}` render when *regular sections* `{{# name }}...{{/ name }}` do not. You can think of the caret `^` as the Mustache "unless".
e1ce058 @groue Simplify the Runtime Guide
authored
82
83 Precisely speaking:
84
85 ### False sections
86
87 If the value is *false*, regular sections are omitted, and inverted sections rendered:
88
89 ```objc
90 id data = @{ @"red": @NO, @"blue": @YES };
91
92 // Renders "Not red"
93 NSString *rendering = [GRMustacheTemplate renderObject:data
94 fromString:@"{{#red}}Red{{/red}}{{^red}}Not red{{/red}}"
95 error:NULL];
96
97 // Renders "Blue"
98 NSString *rendering = [GRMustacheTemplate renderObject:data
99 fromString:@"{{#blue}}Blue{{/blue}}{{^blue}}Not blue{{/blue}}"
100 error:NULL];
101
102 ```
103
bd73358 @groue Wording
authored
104 When an inverted sections follows a regular section with the same expression, you can use the short `{{# name }}...{{^ name }}...{{/ name }}` form, avoiding the closing tag for `{{# name }}`. Think of "if ... else ... end". For brevity's sake, you can also omit the expression after the opening tag: `{{#name}}...{{^}}...{{/}}` is valid.
cc892a6 @groue Runtime Guide clean up
authored
105
e1ce058 @groue Simplify the Runtime Guide
authored
106 The full list of false values are:
cc892a6 @groue Runtime Guide clean up
authored
107
e1ce058 @groue Simplify the Runtime Guide
authored
108 - `nil` and missing keys
cc892a6 @groue Runtime Guide clean up
authored
109 - `[NSNull null]`
110 - `NSNumber` instances whose `boolValue` method returns `NO`
7704634 @groue Runtime Guide WIP
authored
111 - empty strings `@""`
e1ce058 @groue Simplify the Runtime Guide
authored
112 - empty enumerables.
cc892a6 @groue Runtime Guide clean up
authored
113
e1ce058 @groue Simplify the Runtime Guide
authored
114 They all prevent Mustache sections `{{# name }}...{{/ name }}` rendering.
cc892a6 @groue Runtime Guide clean up
authored
115
e1ce058 @groue Simplify the Runtime Guide
authored
116 They all trigger inverted sections `{{^ name }}...{{/ name }}` rendering.
cc892a6 @groue Runtime Guide clean up
authored
117
e1ce058 @groue Simplify the Runtime Guide
authored
118 ### Enumerable sections
cc892a6 @groue Runtime Guide clean up
authored
119
7e94c24 @groue Wording
authored
120 If the value attached to a section conforms to the [NSFastEnumeration](http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocFastEnumeration.html) protocol (except NSDictionary), regular sections are rendered as many times as there are items in the enumerable object:
cc892a6 @groue Runtime Guide clean up
authored
121
e1ce058 @groue Simplify the Runtime Guide
authored
122 ```objc
123 NSArray *friends = @[
124 [Person personWithName:@"Dennis"],
125 [Person personWithName:@"Eugene"],
126 [Person personWithName:@"Fiona"]];
127 id data = @{ @"friends": friends };
128
129 NSString *templateString = @"My friends are:\n"
130 @"{{# friends }}"
131 @"- {{ name }}\n"
132 @"{{/ friends }}";
133
4f170ea @groue Typos
authored
134 // My friends are:
e1ce058 @groue Simplify the Runtime Guide
authored
135 // - Dennis
136 // - Eugene
137 // - Fiona
138 NSString *rendering = [GRMustacheTemplate renderObject:data
139 fromString:templateString
140 error:NULL];
141 ```
cc892a6 @groue Runtime Guide clean up
authored
142
e1ce058 @groue Simplify the Runtime Guide
authored
143 Each item in the collection gets, each on its turn, available for the key lookup: that is how the `{{ name }}` tag renders each of my friend's name.
cc892a6 @groue Runtime Guide clean up
authored
144
e1ce058 @groue Simplify the Runtime Guide
authored
145 Inverted sections render if and only if the collection is empty:
146
147 ```objc
148 id data = @{ @"friends": @[] }; // empty array
149
a856baf @groue Explicitely states support for implicit iterator
authored
150 NSString *templateString = @"{{^ friends }}"
e1ce058 @groue Simplify the Runtime Guide
authored
151 @"I have no friend, sob."
152 @"{{/ friends }}";
153
4f170ea @groue Typos
authored
154 // I have no friend, sob.
e1ce058 @groue Simplify the Runtime Guide
authored
155 NSString *rendering = [GRMustacheTemplate renderObject:data
156 fromString:templateString
157 error:NULL];
158 ```
cc892a6 @groue Runtime Guide clean up
authored
159
a856baf @groue Explicitely states support for implicit iterator
authored
160 #### Rendering a collection of strings
161
162 You may render a collection of strings with the dot expression `.`, aka "implicit iterator":
163
164 ```objc
165 id data = @{ @"items": @[@"Ham", @"Jam"] };
166
167 NSString *templateString = @"{{# items }}"
168 @"- {{ . }}"
169 @"{{/ items }}";
170
171 // - Ham
172 // - Jam
173 NSString *rendering = [GRMustacheTemplate renderObject:data
174 fromString:templateString
175 error:NULL];
176 ```
177
178
e1ce058 @groue Simplify the Runtime Guide
authored
179 #### Rendering a section once when a collection contains several items
cc892a6 @groue Runtime Guide clean up
authored
180
e1ce058 @groue Simplify the Runtime Guide
authored
181 Sections render as many times as they contain items.
cc892a6 @groue Runtime Guide clean up
authored
182
7658aa7 @groue Typo
authored
183 However, you may want to render a section *once* if and only if a collection is not empty. For example, when rendering a single `<ul>` HTML element that wraps several `<li>`.
cc892a6 @groue Runtime Guide clean up
authored
184
4f170ea @groue Typos
authored
185 A template that is compatible with [other Mustache implementations](https://github.com/defunkt/mustache/wiki/Other-Mustache-implementations) needs an extra boolean key that states whether the collection is empty or not:
cc892a6 @groue Runtime Guide clean up
authored
186
e1ce058 @groue Simplify the Runtime Guide
authored
187 ```objc
188 NSArray *friends = ...;
189 id data = @{
8874ccb @groue Typo
authored
190 @"hasFriends": @(friends.count > 0),
e1ce058 @groue Simplify the Runtime Guide
authored
191 @"friends": friends };
192
193 NSString *templateString = @"{{# hasFriends }}"
194 @"<ul>"
195 @" {{# friends }}"
196 @" <li>{{ name }}</li>"
197 @" {{/ friends }}";
198 @"</ul>"
199 @"{{/ hasFriends }}";
200
201 // <ul>
202 // <li>Dennis</li>
203 // <li>Eugene</li>
204 // <li>Fiona</li>
205 // </ul>
206 NSString *rendering = [GRMustacheTemplate renderObject:data
207 fromString:templateString
208 error:NULL];
209 ```
cc892a6 @groue Runtime Guide clean up
authored
210
12d1a3d @groue Wording
authored
211 If you do not care about compatibility, you can simply use the `count` property of NSArray, and use the fact that GRMustache considers zero numbers as false:
cc892a6 @groue Runtime Guide clean up
authored
212
eac53f1 @groue Update the doc with a warning against issue #70
authored
213 > WARNING (February 27, 2013): it looks that accessing NSArray's count crashes on arm64 (see [issue #70](https://github.com/groue/GRMustache/issues/70)).
214 >
215 > Please avoid this technique until this issue is solved.
216
e1ce058 @groue Simplify the Runtime Guide
authored
217 ```objc
218 NSArray *friends = ...;
219 id data = @{ @"friends": friends };
220
221 NSString *templateString = @"{{# friends.count }}"
222 @"<ul>"
223 @" {{# friends }}"
224 @" <li>{{ name }}</li>"
225 @" {{/ friends }}";
226 @"</ul>"
227 @"{{/ friends.count }}";
228
229 // <ul>
230 // <li>Dennis</li>
231 // <li>Eugene</li>
232 // <li>Fiona</li>
233 // </ul>
234 NSString *rendering = [GRMustacheTemplate renderObject:data
235 fromString:templateString
236 error:NULL];
237 ```
f26037b @groue More guide rewriting for 6.0.0
authored
238
86dfa82 @groue runtime.md guide focuses on valueForKey:, description, and NSFastEnum…
authored
239
e1ce058 @groue Simplify the Runtime Guide
authored
240 ### Lambda sections
cc892a6 @groue Runtime Guide clean up
authored
241
3ecaef7 @groue mustache.github.com -> mustache.github.io
authored
242 Mustache defines [lambda sections](http://mustache.github.io/mustache.5.html), that is, sections that execute your own application code, and allow you to extend the core Mustache engine.
cc892a6 @groue Runtime Guide clean up
authored
243
e1ce058 @groue Simplify the Runtime Guide
authored
244 Such sections are fully documented in the [Rendering Objects Guide](rendering_objects.md), but here is a preview:
cc892a6 @groue Runtime Guide clean up
authored
245
e1ce058 @groue Simplify the Runtime Guide
authored
246 ```objc
247 id data = @{
248 @"name1": @"Gustave",
249 @"name2": @"Henriett" };
250
251 NSString *templateString = @"{{#localize}}Hello {{name1}}, do you know {{name2}}?{{/localize}}";
252
253 // Assuming a Spanish locale:
254 // Hola Gustave, sabes Henriett?
255 NSString *rendering = [GRMustacheTemplate renderObject:data
256 fromString:templateString
257 error:NULL];
258 ```
cc892a6 @groue Runtime Guide clean up
authored
259
bd53b5f @groue Obsolete number formatting and localization sample code
authored
260 The `localize` key is attached to a rendering object that is built in the [standard library](standard_library.md) shipped with GRMustache.
cc892a6 @groue Runtime Guide clean up
authored
261
262
e1ce058 @groue Simplify the Runtime Guide
authored
263 ### Other sections
cc892a6 @groue Runtime Guide clean up
authored
264
8fde787 @groue Guides WIP
authored
265 When a section renders a value that is not false, not enumerable, not a [rendering object](rendering_objects.md), it renders once, making the value available for the key lookup inside the section:
e1ce058 @groue Simplify the Runtime Guide
authored
266
267 ```objc
268 Person *ignacio = [Person personWithName:@"Ignacio"];
269 id data = @{ @"person": ignacio };
270
271 // Renders "Hello Ignacio!"
272 NSString *templateString = @"{{# person }}Hello {{ name }}!{{/ person }}";
273 NSString *rendering = [GRMustacheTemplate renderObject:data
274 fromString:templateString
275 error:NULL];
cc892a6 @groue Runtime Guide clean up
authored
276 ```
86dfa82 @groue runtime.md guide focuses on valueForKey:, description, and NSFastEnum…
authored
277
3436a68 @groue Explicitely states support for expressions in section tags
authored
278 ### Expressions in sections
279
280 Just as variable tags, section tags render any well-formed expressions:
281
282 ```objc
283 id data = @{
284 @"person": @{
285 @"friends": @[
286 [Person personWithName:@"José"],
287 [Person personWithName:@"Karl"],
288 [Person personWithName:@"Lubitza"]]
289 }
290 };
291
292 NSString *templateString = @"{{# withPosition(person.friends) }}"
293 @" {{ position }}: {{ name }}"
294 @"{{/}}";
295
296 // 1: José
d1c09d9 @groue Typo
authored
297 // 2: Karl
3436a68 @groue Explicitely states support for expressions in section tags
authored
298 // 3: Lubitza
299 NSString *rendering = [GRMustacheTemplate renderObject:data
300 fromString:templateString
301 error:NULL];
302 ```
303
8fde787 @groue Guides WIP
authored
304 The `withPosition` filter returns a [rendering object](rendering_objects.md) that makes the `position` key available inside the section. It is described in the [Collection Indexes Sample Code](sample_code/indexes.md).
3436a68 @groue Explicitely states support for expressions in section tags
authored
305
3d83fb0 @groue GitHub Flavored Markdown
authored
306
e1ce058 @groue Simplify the Runtime Guide
authored
307 The Context Stack
308 -----------------
309
310 We have seen that values rendered by sections are made available for the key lookup inside the section.
311
312 As a matter of fact, objects that were the context of enclosing sections are still available: the latest object has just entered the top of the *context stack*.
313
314 An example should make this clearer. Let's consider the template below:
315
316 {{# title }}
317 {{ length }}
318 {{/ title }}
319
320 {{# title }}
321 {{ title }}
322 {{/ title }}
323
324 In the first section, the `length` key will be fetched from the `title` string which has just entered the context stack: it will be rendered as "6" if the title is "Hamlet".
325
4970396 @groue Wording
authored
326 In the last section, the title string is still the context. However it has no `title` key. Thus GRMustache looks for it in the enclosing context, finds again the title string, and renders it:
e1ce058 @groue Simplify the Runtime Guide
authored
327
328 6
329 Hamlet
330
331 This technique allows, for example, the conditional rendering of a `<h1>` HTML tag if and only if the title is not empty (empty strings are considered false, see "false sections" above):
332
333 {{# title }}
334 <h1>{{ title }}</h1> {{! rendered if there is a title }}
335 {{/ title }}
336
337
13c0ac2 @groue Wording
authored
338 Fine tuning of key lookup
339 -------------------------
340
341 ### Focus on the current context
d31d8cf @groue runtime.md guide focuses on valueForKey:, description, and NSFastEnum…
authored
342
e1ce058 @groue Simplify the Runtime Guide
authored
343 These three template snippets are quite similar, but not stricly equivalent:
d31d8cf @groue runtime.md guide focuses on valueForKey:, description, and NSFastEnum…
authored
344
e1ce058 @groue Simplify the Runtime Guide
authored
345 - `...{{# foo }}{{ bar }}{{/ foo }}...`
346 - `...{{# foo }}{{ .bar }}{{/ foo }}...`
347 - `...{{ foo.bar }}...`
f5fb58f @groue wording
authored
348
cc892a6 @groue Runtime Guide clean up
authored
349 The first will look for `bar` anywhere in the context stack, starting with the `foo` object.
350
e1ce058 @groue Simplify the Runtime Guide
authored
351 The two others are identical: they ensure the `bar` key comes from the very `foo` object. If `foo` is not found, the `bar` lookup will fail as well, regardless of `bar` keys defined by enclosing contexts.
cc892a6 @groue Runtime Guide clean up
authored
352
13c0ac2 @groue Wording
authored
353 ### Protected contexts
cc892a6 @groue Runtime Guide clean up
authored
354
13c0ac2 @groue Wording
authored
355 *Protected contexts* let you make sure some keys get always evaluated to the same value, regardless of objects that enter the context stack. Check the [Protected Contexts Guide](protected_contexts.md).
daa3e3e @groue Runtime Guide links to Tag Delegates and Protected Context Guides
authored
356
13c0ac2 @groue Wording
authored
357 ### Tag delegates
daa3e3e @groue Runtime Guide links to Tag Delegates and Protected Context Guides
authored
358
13c0ac2 @groue Wording
authored
359 Values extracted from the context stack are directly rendered unless you had some *tag delegates* enter the game. They help you render default values for missing keys, for example. See the [Tag Delegates Guide](delegate.md) for a full discussion.
daa3e3e @groue Runtime Guide links to Tag Delegates and Protected Context Guides
authored
360
361
e1ce058 @groue Simplify the Runtime Guide
authored
362 Detailed description of GRMustache handling of `valueForKey:`
363 -------------------------------------------------------------
cc892a6 @groue Runtime Guide clean up
authored
364
3f366df @groue v6.9.0
authored
365 As seen above, GRMustache looks for a key in your data objects with the `objectForKeyedSubscript:` and `valueForKey:` methods. If an object responds to `objectForKeyedSubscript:`, this method is used. For other objects, `valueForKey:` is used. With some extra bits described below.
cc892a6 @groue Runtime Guide clean up
authored
366
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
367
368 ### NSUndefinedKeyException Handling
cc892a6 @groue Runtime Guide clean up
authored
369
370 NSDictionary never complains when asked for an unknown key. However, the default NSObject implementation of `valueForKey:` raises an `NSUndefinedKeyException`.
371
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
372 *GRMustache catches those exceptions*, so that the key lookup can continue down the context stack.
373
374
375 ### NSUndefinedKeyException Prevention
376
3f366df @groue v6.9.0
authored
377 Objective-C exceptions have several drawbacks, particularly:
378
379 1. they play badly with autorelease pools, and are reputed to leak memory.
380 2. they usually stop your debugger when you are developping your application.
381
382 The first point is indeed a matter of worry: Apple does not guarantee that exceptions raised by `valueForKey:` do not leak memory. However, I never had any evidence of such a leak from NSObject's implementation.
383
384 Should you still worry, we recommend that you avoid the `valueForKey:` method altogether. Instead, implement the [keyed subscripting](http://clang.llvm.org/docs/ObjectiveCLiterals.html#dictionary-style-subscripting) `objectForKeyedSubscript:` method on objects that you provide to GRMustache.
385
386 The second point is valid also: NSUndefinedKeyException raised by template rendering may become a real annoyance when you are debugging your project, because it's likely you've told your debugger to stop on every Objective-C exceptions.
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
387
3f366df @groue v6.9.0
authored
388 You can avoid them as well: make sure you invoke once, early in your application, the following method:
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
389
390 ```objc
391 [GRMustache preventNSUndefinedKeyExceptionAttack];
392 ```
393
394 Depending on the number of NSUndefinedKeyException that get prevented, you will experience a slight performance hit, or a performance improvement.
395
2612858 @groue Wording
authored
396 Since the main use case for this method is to avoid Xcode breaks on rendering exceptions, the best practice is to conditionally invoke this method, using the [NS_BLOCK_ASSERTIONS](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html) that helps identifying the Debug configuration of your targets:
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
397
398 ```objc
399 #if !defined(NS_BLOCK_ASSERTIONS)
2612858 @groue Wording
authored
400 // Debug configuration: keep GRMustache quiet
3c71cb8 @groue Restore documentation for [GRMustache preventNSUndefinedKeyExceptionA…
authored
401 [GRMustache preventNSUndefinedKeyExceptionAttack];
402 #endif
403 ```
404
cc892a6 @groue Runtime Guide clean up
authored
405
98cc7bd @groue Structure
authored
406 ### NSArray, NSSet, NSOrderedSet
cc892a6 @groue Runtime Guide clean up
authored
407
408 *GRMustache shunts the valueForKey: implementation of Foundation collections to NSObject's one*.
409
410 It is little know that the implementation of `valueForKey:` of Foundation collections return another collection containing the results of invoking `valueForKey:` using the key on each of the collection's objects.
411
412 This is very handy, but this clashes with the [rule of least surprise](http://www.catb.org/~esr/writings/taoup/html/ch01s06.html#id2878339) in the context of Mustache template rendering.
413
414 First, `{{collection.count}}` would not render the number of objects in the collection. `{{#collection.count}}...{{/}}` would not conditionally render if and only if the array is not empty. This has bitten at least [one GRMustache user](https://github.com/groue/GRMustache/issues/21), and this should not happen again.
415
d1c09d9 @groue Typo
authored
416 Second, `{{#collection.name}}{{.}}{{/}}` would render the same as `{{#collection}}{{name}}{{/}}`. No sane user would ever try to use the convoluted first syntax. But sane users want a clean and clear failure when their code has a bug, leading to GRMustache not render the object they expect. When `object` resolves to an unexpected collection, `object.name` should behave like a missing key, not like a key that returns an unexpected collection with weird and hard-to-debug side effects.
f5fb58f @groue wording
authored
417
cc892a6 @groue Runtime Guide clean up
authored
418 Based on this rationale, GRMustache uses the implementation of `valueForKey:` of `NSObject` for arrays, sets, and ordered sets. As a consequence, the `count` key can be used in templates, and no unexpected collections comes messing with the rendering.
f5fb58f @groue wording
authored
419
1a1555f @groue guides wip
authored
420
7704634 @groue Runtime Guide WIP
authored
421 Compatibility with other Mustache implementations
422 -------------------------------------------------
423
424 The [Mustache specification](https://github.com/mustache/spec) does not enforce the list of *false* values, the values that trigger or prevent the rendering of sections and inverted sections:
425
426 There is *no guarantee* that `{{# value }}...{{/ value }}` and `{{^ value }}...{{/ value }}` will render the same, provided with the exact same input, in all Mustache implementations.
427
428 That's unfortunate. Anyway, for the record, here is a reminder of all false values in GRMustache:
429
430 - `nil` and missing keys
431 - `[NSNull null]`
432 - `NSNumber` instances whose `boolValue` method returns `NO`
433 - empty strings `@""`
434 - empty enumerables.
435
48b63af @groue ViewModel guide
authored
436 [up](../../../../GRMustache#documentation), [next](view_model.md)
Something went wrong with that request. Please try again.