UI problem with iOS 16 / iPadOS 16

It seems that anything that triggers what JUCE considers a modal (popup, file browser, etc.) does not work in iOS 16; it goes in to some loop I can’t catch, and locks the UI.

This is unrelated to JUCE_MODAL_LOOPS_PERMITTED (a popup or file browser won’t even build for iOS, of course, without that macro.) Has anyone experienced this? I can’t find anything else in the forum. It is affecting our entire product line, both JUCE 6.5 and JUCE 7.

1 Like

I just went through all the commits in the dev branch of JUCE on GitHub and it doesn’t seem like there is anything in there specifically addressing this. Any help appreciated.

EDIT: Further to this, I built the dev branch, C++20, and the problem still exists, so there are no fixes in the queue for this. I can’t believe I’m the only person to see it.

Hi, just upgraded my iPad and have no problems opening a file browser or a popup.

I have drilled down a bit, and discovered this is generally an async problem.

Older products that do not use APVTS tend to use PopupMenu rather than ComboBox, because it is somewhat easier to deal with. Back in the day (i.e. two weeks ago before iOS 16) one would instance a popup menu like so:

const int result = menu_grain_dir->showMenu(PopupMenu::Options().withParentComponent (this->getTopLevelComponent())
.withTargetComponent (this) .withTargetScreenArea(ctrl_btn_grain_dir->getBounds()));

This worked fine up to iOS 15. Now, it does not.

This works:

menu_grain_dir->showMenuAsync(PopupMenu::Options().withParentComponent (this->getTopLevelComponent())
.withTargetComponent (this) .withTargetScreenArea(ctrl_btn_grain_dir->getBounds()));

But obviously it needs a lambda, as showMenuAsync does not return the index of the selected. (That wouldn’t, of course, be asynchronous, so I don’t blame anyone.)

I assume that the file browsers et al are exhibiting the same behavior.

Okay, for those of you that are trying to puzzle this out, here is a method that will work in iOS 16 (and all previous iOS) with JUCE 6 and 7.

Note that if you use ComboBox and AudioProcessorValueTreeState you don’t need to faff about with this. However, we have several older products that were made before we switched to APVTS.

my_menu->showMenuAsync(PopupMenu::Options().withParentComponent (this->getTopLevelComponent())
                  .withTargetComponent (this)
                  .withTargetScreenArea(my_btn->getBounds()),
                  // Lambda
                  [this](int result)
                    {
                        // do a thing with result, just like before.
                    }
                  );

This will also be necessary for AU, AUv3, and standalones on macOS Ventura.

1 Like

Just to give some update, we did inquire at Apple about this problem, and the only advice we got so far is “don’t use modal loops”, because it will cause all sorts of problems. We still think this should have been acknowledged more as a breaking change as opposed to starting to fail unannounced. I’ll update the thread if we know more.

In fairness to you, it is a breaking change from Apple, not JUCE.

But it is absolutely a breaking change.