UIAlertController исчезает с iOS 13

У меня есть следующая функция, которая вызывает UIAlert, который позволяет пользователю обновить настройку тактильной обратной связи:

- (void)requestHapticSetting{
    UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    alertWindow.rootViewController = [[UIViewController alloc] init];
    alertWindow.windowLevel = UIWindowLevelAlert + 1;
    [alertWindow makeKeyAndVisible];

    if(isHapticOn){
        hapticMessage = @"Haptic feedback is currently\nturned ON.\nPlease update preference.";
    }
    else {
        hapticMessage = @"Haptic feedback is currently\nturned OFF.\nPlease update preference.";
    }

    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Haptic Setting"
                                                                   message:hapticMessage
                                                            preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction* onAction = [UIAlertAction actionWithTitle:@"TURN ON" style:UIAlertActionStyleDefault
                                                     handler:^(UIAlertAction * action) {
                                                         [self saveHapticSettingOn];
                                                     }];

    UIAlertAction* offAction = [UIAlertAction actionWithTitle:@"TURN OFF" style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction * action) {
                                                          [self saveHapticSettingOff];
                                                      }];
    [alert addAction:offAction];
    [alert addAction:onAction];
    [alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
}

Я использовал это в течение нескольких лет, и он отлично работает.

Однако после обновления до iOS 13 и обновления до последней версии Xcode мое предупреждение появляется менее чем за секунду до закрытия.

Что изменилось, что могло заставить это случиться? Заранее спасибо.


person Reanimation    schedule 28.09.2019    source источник
comment
По сути, это дубликат stackoverflow.com/questions/58131996/, но это в Swift, и его ответ не будет работать должным образом в iOS 13, когда вы поддерживаете сцены.   -  person rmaddy    schedule 28.09.2019
comment
Используете ли вы сцены в своем приложении под iOS 13 или решили полностью отказаться от сцен (чего делать не следует)?   -  person rmaddy    schedule 28.09.2019
comment
@rmaddy Я не совсем уверен. Я использую игровой движок, который генерирует проект Xcode. Добавление этого в прошлом, к сожалению, всегда работало до сих пор. Спасибо.   -  person Reanimation    schedule 28.09.2019


Ответы (2)


Похоже, что изменилось то, что в iOS 12 и предыдущих версиях ваше приложение будет содержать сильную ссылку на окно, просто вызывая [alertWindow makeKeyAndVisible];, в iOS 13 этого больше нет.

Что происходит, так это то, что единственная сильная ссылка на ваш alertWindow находится в вашей requestHapticSetting func, и как только эта функция возвращается, окно уничтожается, таким образом удаляя ваше предупреждение из представления.

Это можно исправить, просто применив сцены iOS 13, но я этого не тестировал. Я могу предложить, что не будет работать должным образом, если вы используете сцены, - это держать окно предупреждения в сильной переменной где-то в вашем коде, а затем использовать его для представления предупреждения. Я бы предложил сделать это в синглтоне или в самом AppDelegate.

//AppDelegate.h
...
@property (strong) UIWindow *alertWindow;
....

//AppDelegate.m
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    self.alertWindow = [[UIWindow alloc] init];
    self.alertWindow.rootViewController = [[UIViewController alloc] init];
    self.alertWindow.windowLevel = UIWindowLevelAlert + 1;
    ...
}
...

//Your class that's presenting the alert
#import "AppDelegate.h"
...
- (void)requestHapticSetting{
    AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication;
    [appDelegate.alertWindow makeKeyAndVisible];
    if(isHapticOn){
        hapticMessage = @"Haptic feedback is currently\nturned ON.\nPlease update preference.";
    } else {
        hapticMessage = @"Haptic feedback is currently\nturned OFF.\nPlease update preference.";
    }

    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Haptic Setting"
                                                               message:hapticMessage
                                                        preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction* onAction = [UIAlertAction actionWithTitle:@"TURN ON" style:UIAlertActionStyleDefault
                                                 handler:^(UIAlertAction * action) {
                                                      [self saveHapticSettingOn];
                                                      [appDelegate.alertWindow setHidden:YES];
                                                 }];

    UIAlertAction* offAction = [UIAlertAction actionWithTitle:@"TURN OFF" style:UIAlertActionStyleDefault
                                                  handler:^(UIAlertAction * action) {
                                                      [self saveHapticSettingOff];
                                                      [appDelegate.alertWindow setHidden:YES];
                                                  }];
    [alert addAction:offAction];
    [alert addAction:onAction];
    [appDelegate.alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
}

Для кода Swift проверьте этот ответ.

person pepsy    schedule 29.09.2019

Я создал вспомогательный класс, который поддерживает новый UIWindowScene, iOS 13.X и swift 5.X. Вы, ребята, можете попробовать

https://github.com/emraz/ERAlertController

person emraz    schedule 31.03.2020