really modal alert in i(Pad)OS 18

I need a really modal alert, i.e., one which runs and allows the user interaction and closes and returns the selected option inside of a single method.

(I need to serve an API which calls my callback, presuming I show an alert, get the user's decision, and return it from that very callback. The callback comes in the main thread.)

What's the proper way to do this in i(Pad)OS 18+? Thanks!

For reference, up to 17, the following code worked nicely; in 18, it does not anymore:

    volatile BOOL __block stillRuns=YES;
    UIAlertController* ac=[UIAlertController alertControllerWith... preferredStyle:UIAlertControllerStyleAlert];
    [ac addAction:[UIAlertAction actionWith... handler:^(UIAlertAction * _Nonnull action) {
        stillRuns=NO;
    }]];
    ...
    [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:ac animated:YES completion:nil];
    while (stillRuns) [NSRunLoop.currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]];
Answered by Frameworks Engineer in 818904022

What you are trying to do is not supported, and did not work on all hardware that ran iOS 17 either. The reason why it has stopped working more widely on iOS 18 is because the behaviors that prevent it from working have been enabled on a wider range of hardware on iOS 18.

Apple's UI Frameworks do not support a general means of presenting UI that blocks execution until a response from the user is delivered. You will need to refactor your application to handle this kind of response asynchronously instead.

Do you get the same results with just the relevant code in a small test project? If so, please share a link to your test project. That'll help us better understand what's going on. If you're not familiar with preparing a test project, take a look at Creating a test project.

This way people can test the results in iOS 17 and iOS 18.

Albert Pascual
  Worldwide Developer Relations.

What you are trying to do is not supported, and did not work on all hardware that ran iOS 17 either. The reason why it has stopped working more widely on iOS 18 is because the behaviors that prevent it from working have been enabled on a wider range of hardware on iOS 18.

Apple's UI Frameworks do not support a general means of presenting UI that blocks execution until a response from the user is delivered. You will need to refactor your application to handle this kind of response asynchronously instead.

https://ocs.cz/CD/testModalAlert.zip

The runloop-based approach so far (up to iOS17) did work for long years without one single problem. If there indeed is a hardware were it would have failed with older iOSen, then it seems none of our many clients ever used that hardware. Weird.

The API which needs to show an alert and return its result is multi-platform and I can't really refactor it.

Hmmm... I guess I might be able to run it completely in a background thread, for all the other callbacks which do not have this problem use performSelectorOnMainThread or something like that, and for this one just let the background thread wait on a semaphore or another kind of lock, run the alert on the main thread normally, and when done, let the background thread go on. Offhand I guess it should work. Nevertheless it seems an indecent heap of work for such a triviality.

Apple's UI frameworks did support such things from the first moment they ever existed, compare please the original NSRunAlertPanel (and current -[NSAlert runModal) APIs. It seems really extremely weird that i(Pad)OS would itentionally not support such a basic functionality :(

really modal alert in i(Pad)OS 18
 
 
Q