Testing for empty dictionaries

So, the following code

if (data.isEmpty()) {

gives:
Error: Array Out Of Bounds Error

when it's "Lang.Dictionary {size: 0}"

Similarly,

if (data.size() == 0) {

Also gave the same error.

So what can I do to test its size so it doesn't crash?!?

  • "has" should be at the top of your Monkey C toolbox.  Each time there is a new "System" level, you want to use it to try new features in what is beta FW for devices, and a reason you want to use -disable-api-has-check-removal so things resolve at runtime and not compile time.

  • I read that as CIQ 3.2 for background, but the API docs say 2.4 otherwise. Great. Another argument for "has".

    I wonder how compile-time optimization for has checks will work here? I see 4 possibilities, for a 2.4 device:

    1) No optimization (has checks are evaluated at run-time)

    2) Compiler performs optimization correctly for both foreground and background: foreground has checks for setValue (and other Storage.*value() functions) will be optimized so has :setValue is true, but background checks for has :setValue will be optimized to false

    3) has :setValue will be true in both foreground and background, at compile-time

    4) has :setValue will be false in both foreground and background, at compile-time

    Obviously 2) would be best, 1) would be ok, but 3) or 4) would be bad.

    Not sure if 2) would even be possible in principle for some hypothetical piece of code that was shared between the background and foreground tho (like a helper function that wraps Storage.setValue())

    It's (seemingly) another reason to prefer run-time has checks.

     any insight on this?

  • This is explicitly called out in the docs

    Conveniently the last line in each method. Caught being lazy and not reading every word because they save the most important stuff until the very end.

  • Conveniently the last line in each method. Caught being lazy and not reading every word because they save the most important stuff until the very end.

    Yeah, I agree it's not the greatest documentation, especially in the case of the docs for setValue(), which is so huge I didn't even want to screencap it. It would be very easy to miss the 3.2 req and related exception.

    Ideally, the 3.2 requirement for background processes would be called out right next to every instance of "since...2.4.0", including the summary at the top of the docs. The way it is now, it seems like an afterthought which was tacked on after the docs were originally written (which is probably what it was, based on the bug report which suggests that the 3.2 req and related exception weren't previously documented on that page.)

    This is what the docs for setValue() look like:

    And the overview, which doesn't mention 3.2 at all:

    Very easy to see how the 3.2 req for background processes could be missed.

  • Your best option would be to use a try / catch for Application.ObjectStoreAccessException. 

  • Your best option would be to use a try / catch for Application.ObjectStoreAccessException. 

    That's fair. My knee-jerk reaction would be to not use has checks in this case as well.

    But I'm curious how they would work for a CIQ 2.4 device nonetheless. This would be especially relevant if you wanted to suport really old devices (CIQ 1), in which case has checks might be necessary after all (unless you use conditional compilation via exclude annotations.)

  • I've been using "excludeAnnotations" to limit the size of applications. For example, if a device doesn't support complications, why include code for complications for that model? Here's en example:

    in monkey.jungle

    base.excludeAnnotations = lowMemoryWatchface;bkgnd32kb;noComplications
    descentmk2.excludeAnnotations = lowMemoryWatchface;bkgnd64kb;hasComplications

    In CrystalView.mc

    (:noComplications)
    function onComplicationUpdated(complicationId) {
    }
    
    (:hasComplications)
    function onComplicationUpdated(complicationId) {
        var complication = Complications.getComplication(complicationId);
        var complicationType = complication.getType();
        var complicationShortLabel = complication.shortLabel;
        var complicationValue = complication.value;
    :
    :
    
    
    
    

    (nice, I was able to paste source code today!)

    It makes developing a but more complicated since I have to maintain two functions for the same thing but it allows the app to remain available for older models by not bloating its code for no reason. How do you handle it yourself?

  • For publishing complications, I use jungles to include the needed xml on devices that can publish.

    In most cases, the code is fairy trivial and not worth the time to mess with jungles to save a handful of bytes.

    I just checked one of by watchfaces that goes back to when ToyboxWeather was first available, that handles complications on support devices, etc...

    It's 52kb on pre ciq 4  devices and 38k on devices with the graphics pool (it uses custom fonts)

  • Yeah, complication was just an example. The one that has most impact is the bkgnd32kb/bkgnd64kb exclusion. It allows me to give more background features to watch with 64KB of background process without hindering the watches with just 32KB of background memory.