Unexpected Type Error on simple setBool(bool) method

Hello,

I get a random error on my published face (reported by ERA).

An Unexpected Type Error that I don't understand...

Here is an extract of my code:

// View.mc
class View extends Ui.WatchFace {
    private var burn as Boolean;
    private var aod as Boolean;

    private var dr as Drawer;

    function initialize() {
        WatchFace.initialize();
        aod = false;
        burn = false;
    }

    function onLayout(dc as Dc) as Void {
        dr = new Drawer(dc);
        burn = System.getDeviceSettings() has :requiresBurnInProtection and System.getDeviceSettings().requiresBurnInProtection;
    }

    function onEnterSleep() as Void {
        aod = true;
        dr.setSleepMode(aod and burn); // <-- Unexpected Type Error on this line
        Ui.requestUpdate();
    }
}

// Drawer.mc
class Drawer {
    private var _dc as Dc;
    private var _sleepMode as Boolean;

    function initialize(dc as Dc) {
        _dc = dc;
        _sleepMode = false;
    }

    function setSleepMode(sleepMode as Boolean) as Void {
        _sleepMode = sleepMode;
    }
}

Can you see what is going on? Could the variable burn become null at some point?

Top Replies

All Replies

  • Could you give us the whole era? 

    It may be worth adding System.println(variable name here); 

    to your code to see what it returns when run.

  • Why are you using “and” as a variable name?

    I strongly suspect that confusion with “and” in your code is really not helpful… try renaming it to something better and then using conventional operators in your logic. 

  • They are using aod not and.

    edit: nevermind I see the and.

  • 1. Why do you set dc to member?

    2. Use && instead of and maybe there is a bug.

    3. there is no all code so show onExitSleep and onShow though

  • Yes use && (it's different than just &).  Maybe onUpdate and not onShow,  That's where you'd do things differently if in low power or not.

  • 2. Use && instead of and maybe there is a bug.

    Yes use && (it's different than just &)

    OP is using "and", not "&".

    According to the CIQ docs, "&&" and "and" are synonymous, or at least they should be.

    developer.garmin.com/.../

  • As psx said,

    "2. Use && instead of and maybe there is a bug."

    It's how it can be determined if there is a bug so it can be corrected.

    I've seen devs confuse && and & so I pointed out they are not the same.

  • As psx said,

    "2. Use && instead of and maybe there is a bug."

    I'm aware of that since I quoted the exact same text.

    I've seen devs confuse && and & so I pointed out they are not the same.

    Comes across as a little condescending imo, since nobody mentioned "&" anywhere and "&&" was already suggested. Will you also remind everyone that "==" and "=" are not the same any time either of those operators are mentioned?

    Anyway, going back to OP's problem, I think it's very unlikely that:

    1) "and" is broken at all (in the sense that it works differently from "&&")

    2) "and" is broken in a way that breaks the 2nd usage but not the first usage (since the 2nd usage uses the value from the first one, due to the details of both usages, and due to the fact that one of the only known ways to make "&&/and" crash is for the 2nd argument to have the wrong type.) (And also due to the fact that the error message is usually not "Unexpected Type Error" when the the 2nd argument to "&&" has the wrong type.)

    I think I see what's actually happening here:

    class View extends Ui.WatchFace {
        private var burn as Boolean;
        private var aod as Boolean;
    
        private var dr as Drawer;
    
        function initialize() {
            WatchFace.initialize();
            aod = false;
            burn = false;
        }
    
        function onLayout(dc as Dc) as Void {
            dr = new Drawer(dc);
            burn = System.getDeviceSettings() has :requiresBurnInProtection and System.getDeviceSettings().requiresBurnInProtection;
        }
    
        function onEnterSleep() as Void {
            aod = true;
            dr.setSleepMode(aod and burn); // <-- Unexpected Type Error on this line
            Ui.requestUpdate();
        }
    }

    dr is uninitialized, so its value is null until onLayout() is called.

    However, dr.setSleep() is called without a null check for dr in onEnterSleep(), which happens to be where the crash happens:

     function onEnterSleep() as Void {
            aod = true;
            dr.setSleepMode(aod and burn); // <-- Unexpected Type Error on this line

    I think when the code crashes, onEnterSleep() is called before onLayout(), which may be unexpected, but seems like it isn't impossible, as per this discussion:

    [https://forums.garmin.com/developer/connect-iq/f/discussion/1228/onentersleep-called-before-onlayout]

    I think the fix is to initialize dr and burn in initialize(), not onLayout(). In any case, ensure that dr.setSleep() is not called until dr is initialized.

  • Thanks. Indeed, this might be true. I expected onLayout to always be called before onEnterSleep but that might not be true. I'll check that and let you know. 

  • Yeah in general, I would write defensive code that makes as few assumptions about this kind of thing (e.g. order of callbacks) as possible.

    Good luck!