App crashes on Fenix after deleting Menu2 item and scrolling near the end

Former Member
Former Member
Environment
SDK: 3.0.3
Device: Fenix 5s, Software version: 10.00
Eclipse: Photon Release (4.8.0), Build id: 20180619-1200

Description
Crash happens after deleting item and whenever last menu item comes into view (i.e. when trying to put focus on last or second last position).
The problem reproduces on Fenix 5s hardware, but not in simulator.

Steps to reproduce:
Source code is provided in listings below and sample project is attached: Menu2-crash-sample.zip
  • Open app;
  • Press Start - first menu item gets deleted;
  • Press Down - menu scrolls down normally;
  • Press Down again - app crashes with "IQ!" icon.

Nothing is getting written in CIQ_LOG.YML.

App log:
Before delete 0
After delete 0


Source code
Full sample project: Menu2-crash-sample.zip. Below are the listings of .mc files.

Menu2App.mc
using Toybox.Application;
using Toybox.WatchUi;

class Menu2App extends Application.AppBase {

function initialize() {
AppBase.initialize();
}

function getInitialView() {
return [ new StartPageView(), new WatchUi.BehaviorDelegate() ];
}
}


StartPageView.mc
using Toybox.WatchUi;

// Since Menu2 cannot be initial view, this dummy view will act as initial view and will redirect to Menu2
class StartPageView extends WatchUi.View {

function initialize() {
WatchUi.View.initialize();
}

function onLayout(dc) {
WatchUi.pushView(ExampleMenu2View.getInstance(), new ExampleMenu2Delegate(), WatchUi.SLIDE_IMMEDIATE);
}
}


ExampleMenu2View.mc
using Toybox.WatchUi;
using Toybox.Application;

class ExampleMenu2View extends WatchUi.Menu2 {
private static var sInstance;

static function getInstance() {
if (sInstance == null) {
sInstance = new ExampleMenu2View();
}
return sInstance;
}

private function initialize() {
WatchUi.Menu2.initialize({:title=>"Reproducing Menu2 bug"});
var totalItems = 5;
for(var i=0; i < totalItems; i += 1) {
addItem(createMenuItem(i));
}
}

function createMenuItem(i) {
return new WatchUi.MenuItem("item #" + i, "menu item #" + i, i, {});
}

function notifyItemDeleted(i) {
System.println("Before delete " + i);
var index = findItemById(i);
deleteItem(index);
System.println("After delete " + i);
}
}


ExampleMenu2Delegate.mc
using Toybox.WatchUi;
using Toybox.System;

class ExampleMenu2Delegate extends WatchUi.Menu2InputDelegate {

function initialize() {
Menu2InputDelegate.initialize();
}

function onSelect(item) {
var itemId = item.getId();
ExampleMenu2View.getInstance().notifyItemDeleted(itemId);
}

function onBack() {
// Exit skipping dummy start page view
System.exit();
}
}
  • I guess I'm trying to figure out what you want this UI to look like and how it's used. It seems that in the delegate, you're trying to remove an item from the menu, and pushing a new view, from the delegate so it could be you're staking up views.

    If you have a menu with items you want disabled, maybe use ToggleMenyItem() ? That way you can also turn things back on if you turned them off by mistake, etc....
  • Former Member
    Former Member
    I guess I'm trying to figure out what you want this UI to look like and how it's used. It seems that in the delegate, you're trying to remove an item from the menu, and pushing a new view, from the delegate so it could be you're staking up views.

    If you have a menu with items you want disabled, maybe use ToggleMenyItem() ? That way you can also turn things back on if you turned them off by mistake, etc....


    Thanks for taking your time looking into this, jim_m_58!

    The menu shows a list of user presets, which user should be able to add/remove/reorder. The list should be dynamic, and I need the possibility to delete them, not just toggle them off. If user deletes item by mistake, he will have possibility to add another one (for sake of simplicity, I did not include that functionality to the example). If there is a better way to achieve dynamic list functionality, I'd be glad if someone could enlighten me. :)

    Views are not being stacked. Delegate notifies the view that user wants to delete the item, and menu view deletes it, without switching to other view. The same menu gets modified, no new views get pushed to the stack.
  • Former Member
    Former Member
    I've set up a ticket for us to look at this. I was able to reproduce the behavior, but I'm not sure what is intended here. I'm running it by the engineering team.

    Thanks,
    -Coleman
  • Former Member
    Former Member
    Thank you, Coleman! And good luck! :)
  • We typically update these when the issue is fixed and we know the fix has been released.

    As with the other issue, the fix required changes to the device firmware. Those changes have been made, but I'm not sure when the will be released.
  • Former Member
    Former Member
    Thanks, Travis! And sorry about being obnoxious!
  • oreznon I have a (pretty ugly) workaround for this that I used in a tiny app, in case you still need the functionality of a dynamic menu.

    You need a parent view for the menu. If the menu is already the top level view, you need a "dummy view" that doesn't draw anything or accept user input -- it just pushes the child view when it's initially shown, and usually pops itself on subsequent shows.

    The idea is that when the dynamic menu is changed, you need to set a flag and pop back to the parent view. The parent view pushes the menu view so it can reinitialize itself. You may also want to save the selected menu index so it'll be as seamless as possible.

    Two obvious downsides:
    - This won't work with animations (or it'll look terrible)
    - If you put a hack in now, how do you know when it's safe to take it out? (I guess the same argument could be applied to ever using the proper functionality once it's fixed.)
  • Former Member
    Former Member
    WillNorthYork , thanks for providing a workaround. I did something similar, but didn't describe it here. I'm sure others who read this will find what you wrote useful.