Closed priteshshah1983 closed 12 years ago
Hi, Pritesh. If you do not mind sharing your templates with some other platforms, the easiest way is to use ’count’, as you have tried. The new way, with filters, is ’{{^ isEmpty(attendees) }}Display me!{{/}}’. It does not invalidate the ’count’ trick, though.
Testing for ’count’ should not crash, and indeed ’{{#attendees.count}}Display me!{{/attendees.count}}’ does NOT crash.
The crash you're experiencing is thus unrelated to this emptiness test. It happens somewhere else. Do you have a stack trace or something?
My bad, it doesn't crash the app, but it throws an exception and I have Xcode set to add a breakpoint on all exceptions. Here is the stack trace: http://tinypic.com/r/1fe7it/6
Please note that I have added the code posted by you (see below), but {{attendees.count}} still throws an exception and doesn't work.
[GRMustache preventNSUndefinedKeyExceptionAttack];
--- Edit ---
Adding a simple example:
NSArray *array1 = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2], nil];
NSString *rendering = [GRMustacheTemplate renderObject:array1
fromString:@"Count is {{count}}"
error:NULL];
Should this work? I get the same error and stack trace as explained above.
Thanks for your help!
OK. Tell me if I understand well:
First, the rendering is done just fine, and you do not experience any crash.
However, despite the prevention of exceptions that should keep your debugger quiet, your breakpoint is still activated.
Does this describe your situation?
OK I get it.
valueForKey has a special behavior when applied to arrays: it returns another array filled with the key applied to its element. Thus {{ count }} generates an array of the key ‘count‘ applied to the NSNumber items, which do not know this key, and raise exceptions which are not prevented by preventNSUndefinedKeyExceptionAttack (it only prevents exceptions raised by the target object itself, the array, not other objects).
Well, this is interesting. I will consider having this guard method catch exceptions sent by array items (its purpose it not to catch them all, but only most of them - I'll check the documentation in case this is not absolutely clear. If there is a bug, it's a documentation bug since its impossible to prevent all exceptions)
So, today, here are your options:
Sorry for the inconvenience.
Second thought:
I plan to keep valueForKey:
as the one and only way to provide values to the rendering engine. NSArray implementation returns another array, even if the key is count
. So, there is absolutely no way {{ count }}
can ever return an actual number.
This leads to a real bug in GRMustache: {{attendees.name}} {{.}} {{/attendees.name}}
outputs the concatenation of the names of the attendees, instead of the empty string. That's because attendees.name
yields an array of names, instead of the expected value nil (array do not have any name
property).
So, thank you very much Pritesh for letting this bug emerge. Its resolution may affect your count
problem, I'll let you know.
Thanks Gwendal! I didn't understand the valueForKey:
behavior before reading your explanation. I'm planning to declare another property 'hasAttendees' as you suggested to keep it simple for now.
That would have been my choice as well :-) Happy Mustache, and thanks again for the indirect bug report :-)
@priteshshah1983 GRMustache 4.3.2 fixes the {{#attendees.name}} {{.}} {{/attendees.name}}
bug. As a consequence, {{#attendees.count}}Display me!{{/attendees.count}}
will never render, even for non-empty arrays, but won't raise any exception, because the default implementation of valueForKey: is now avoided for NSArray, NSSet and NSOrderedSet, the three foundation classes that return new collections instead of performing a property/method lookup.
Thanks for fixing this!
@priteshshah1983 GRMustache 5.5.1 restores the ability to use the count
key in templates, while preventing the bugs we have discovered together. See https://github.com/groue/GRMustache/blob/master/Guides/runtime/context_stack.md#nsarray-nsset-nsorderedset
Is it possible to access NSArray's count property in the Mustache template? For example, I have an attendees NSArray and I would like display some snippet exactly once if attendees.count > 0.
{{#attendees.count}}Display me!{{/attendees.count}} // crashes!
If I use {{#attendees}}Display me!{{/attendees}} // Display me! is displayed multiple times.
Do I need to define a filter? Or is there an easier way?