Simpler method to check for GCM / Garmin Express Idiosyncracies

I'm currently doing...
CF1 = (app.getProperty("CF_1")!= null && !app.getProperty("CF_1").equals("")) ? app.getProperty("CF_1") : 999 ;

just to check if the usersettings portion of things is null or blank. This is taking up quite a lot of code space.
  • I've got all of my settings access going through a single class...

    module Settings {
        using Toybox.Application as App;
        using Toybox.Lang as Lang;
    
        function getProperty(key, value) {
    
        var val = App.getApp().getProperty(key);
            if (val == null) {
                return value; // return the default
            }
    
            return val;
            }
    
        function setProperty(key, value) {
            App.getApp().setProperty(key, value);
        }
    }



    This does add a function call to get the app (this could be resolved easily), but it has the advantage that I don't have to pass the app around all of the time, and I get a single point of entry for accessing the object store.

    If you extended that, you'd only need to add the check in one place...

    function getStringProperty(key, dflt) {
        assert(dflt instanceof Lang.String);
    
        var val = App.getApp().getProperty(key);
        if (val != null && val instanceof Lang.String && !"".equals(val)) {
            return val;
        }
    
        return dflt;
    }
    
    function getBooleanProperty(key, dflt) {
        return getTypedProperty(key, dflt, Lang.Boolean);
    }
    
    function getNumberProperty(key, dflt) {
        return getTypedProperty(key, dflt, Lang.Number);
    }
    
    function getFloatProperty(key, dflt) {
        return getFloatProperty(key, dflt, Lang.Float);
    }
    
    function getDoubleProperty(key, dflt) {
        return getTypedProperty(key, dflt, Lang.Double);
    }
    
    //...
    
    // I'm not sure this works, but I believe it should
    hidden function getTypedProperty(key, dflt, type) {
        assert(dflt instanceof type);
    
        var val = App.getApp().getProperty(key);
        if (val instanceof type) {
            return val;
        }
    
        return dflt;
    }



    Assuming you can use this, now you just write...

    CF1 = Settings.getNumberProperty("CF_1", 999);

  • I do something similar to Travis, but I have different versions checking for specific types

    for example, I have

    function getNumberProperty(key, value) {

    and

    function getBooleanProperty(key, value) {

    and in the code, they check "instanceof Number" and "instanceof Boolean", as there are (or were) cases when a "number" would come back from GCM as a string and not a number, for example.

    If you are expecting a number and get a string, you can also use toNumber() on it and get the number.

    Another thing to watch is checking the range of numbers where it fits. I've seen cases where the latest version of settings is used by GCM, where an older version of something is still on the watch.

    For example, say you have a list that returns 0 to 4 in "version 1" but in "version 2" you add two new items, and can now set 0 to 6.

    In "version 1", check for 0 to 4, and "version 2" check for 0 to 6 (to be ready for "version 3").

    Otherwise, the "version 2" settings could be sent to "version 1" on the watch, meaning "version 1" could see 5 or 6 in this case and cause problems.