iOS: show message boxes using the new UIAlertController APIs when supported, rather than the deprecated UIAlertView.
authorAlex Szpakowski <slime73@gmail.com>
Fri, 25 Sep 2015 15:17:20 -0300
changeset 98798465a79c9f85
parent 9878 63f03a567fe3
child 9880 3bbeb623181c
iOS: show message boxes using the new UIAlertController APIs when supported, rather than the deprecated UIAlertView.

UIAlertController is also supported on tvOS, whereas UIAlertView is not.
src/joystick/iphoneos/SDL_sysjoystick.m
src/video/uikit/SDL_uikitmessagebox.m
src/video/uikit/SDL_uikitopengles.m
src/video/uikit/SDL_uikitviewcontroller.h
src/video/uikit/SDL_uikitviewcontroller.m
     1.1 --- a/src/joystick/iphoneos/SDL_sysjoystick.m	Mon Sep 21 21:19:37 2015 +0200
     1.2 +++ b/src/joystick/iphoneos/SDL_sysjoystick.m	Fri Sep 25 15:17:20 2015 -0300
     1.3 @@ -181,7 +181,7 @@
     1.4  #endif /* !SDL_EVENTS_DISABLED */
     1.5  }
     1.6  
     1.7 -SDL_JoystickDeviceItem *
     1.8 +static SDL_JoystickDeviceItem *
     1.9  SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
    1.10  {
    1.11      SDL_JoystickDeviceItem *prev = NULL;
    1.12 @@ -374,12 +374,14 @@
    1.13  }
    1.14  
    1.15  /* Function to determine if this joystick is attached to the system right now */
    1.16 -SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
    1.17 +SDL_bool
    1.18 +SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
    1.19  {
    1.20      return joystick->hwdata != NULL;
    1.21  }
    1.22  
    1.23 -static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
    1.24 +static void
    1.25 +SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
    1.26  {
    1.27      const float maxgforce = SDL_IPHONE_MAX_GFORCE;
    1.28      const SInt16 maxsint16 = 0x7FFF;
    1.29 @@ -579,7 +581,8 @@
    1.30      numjoysticks = 0;
    1.31  }
    1.32  
    1.33 -SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
    1.34 +SDL_JoystickGUID
    1.35 +SDL_SYS_JoystickGetDeviceGUID( int device_index )
    1.36  {
    1.37      SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
    1.38      SDL_JoystickGUID guid;
    1.39 @@ -591,7 +594,8 @@
    1.40      return guid;
    1.41  }
    1.42  
    1.43 -SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
    1.44 +SDL_JoystickGUID
    1.45 +SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
    1.46  {
    1.47      SDL_JoystickGUID guid;
    1.48      if (joystick->hwdata) {
     2.1 --- a/src/video/uikit/SDL_uikitmessagebox.m	Mon Sep 21 21:19:37 2015 +0200
     2.2 +++ b/src/video/uikit/SDL_uikitmessagebox.m	Fri Sep 25 15:17:20 2015 -0300
     2.3 @@ -24,15 +24,103 @@
     2.4  
     2.5  #include "SDL.h"
     2.6  #include "SDL_uikitvideo.h"
     2.7 -
     2.8 +#include "SDL_uikitwindow.h"
     2.9  
    2.10  /* Display a UIKit message box */
    2.11  
    2.12  static SDL_bool s_showingMessageBox = SDL_FALSE;
    2.13  
    2.14 +SDL_bool
    2.15 +UIKit_ShowingMessageBox()
    2.16 +{
    2.17 +    return s_showingMessageBox;
    2.18 +}
    2.19 +
    2.20 +static void
    2.21 +UIKit_WaitUntilMessageBoxClosed(const SDL_MessageBoxData *messageboxdata, int *clickedindex)
    2.22 +{
    2.23 +    *clickedindex = messageboxdata->numbuttons;
    2.24 +
    2.25 +    @autoreleasepool {
    2.26 +        /* Run the main event loop until the alert has finished */
    2.27 +        /* Note that this needs to be done on the main thread */
    2.28 +        s_showingMessageBox = SDL_TRUE;
    2.29 +        while ((*clickedindex) == messageboxdata->numbuttons) {
    2.30 +            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    2.31 +        }
    2.32 +        s_showingMessageBox = SDL_FALSE;
    2.33 +    }
    2.34 +}
    2.35 +
    2.36 +static BOOL
    2.37 +UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    2.38 +{
    2.39 +#ifdef __IPHONE_8_0
    2.40 +    int i;
    2.41 +    int __block clickedindex = messageboxdata->numbuttons;
    2.42 +    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
    2.43 +    UIWindow *window = nil;
    2.44 +    UIWindow *alertwindow = nil;
    2.45 +
    2.46 +    if (![UIAlertController class]) {
    2.47 +        return NO;
    2.48 +    }
    2.49 +
    2.50 +    UIAlertController *alert;
    2.51 +    alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
    2.52 +                                                message:@(messageboxdata->message)
    2.53 +                                         preferredStyle:UIAlertControllerStyleAlert];
    2.54 +
    2.55 +    for (i = 0; i < messageboxdata->numbuttons; i++) {
    2.56 +        UIAlertAction *action;
    2.57 +        UIAlertActionStyle style = UIAlertActionStyleDefault;
    2.58 +
    2.59 +        if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
    2.60 +            style = UIAlertActionStyleCancel;
    2.61 +        }
    2.62 +
    2.63 +        action = [UIAlertAction actionWithTitle:@(buttons[i].text)
    2.64 +                                          style:style
    2.65 +                                        handler:^(UIAlertAction *action) {
    2.66 +                                            clickedindex = i;
    2.67 +                                        }];
    2.68 +        [alert addAction:action];
    2.69 +    }
    2.70 +
    2.71 +    if (messageboxdata->window) {
    2.72 +        SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
    2.73 +        window = data.uiwindow;
    2.74 +    }
    2.75 +
    2.76 +    if (window == nil || window.rootViewController == nil) {
    2.77 +        alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    2.78 +        alertwindow.rootViewController = [UIViewController new];
    2.79 +        alertwindow.windowLevel = UIWindowLevelAlert;
    2.80 +
    2.81 +        window = alertwindow;
    2.82 +
    2.83 +        [alertwindow makeKeyAndVisible];
    2.84 +    }
    2.85 +
    2.86 +    [window.rootViewController presentViewController:alert animated:YES completion:nil];
    2.87 +    UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
    2.88 +
    2.89 +    if (alertwindow) {
    2.90 +        alertwindow.hidden = YES;
    2.91 +    }
    2.92 +
    2.93 +    *buttonid = messageboxdata->buttons[clickedindex].buttonid;
    2.94 +    return YES;
    2.95 +#else
    2.96 +    return NO;
    2.97 +#endif /* __IPHONE_8_0 */
    2.98 +}
    2.99 +
   2.100 +/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
   2.101 +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
   2.102  @interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
   2.103  
   2.104 -@property (nonatomic, assign) int clickedIndex;
   2.105 +@property (nonatomic, assign) int *clickedIndex;
   2.106  
   2.107  @end
   2.108  
   2.109 @@ -40,52 +128,62 @@
   2.110  
   2.111  - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
   2.112  {
   2.113 -    _clickedIndex = (int)buttonIndex;
   2.114 +    if (_clickedIndex != NULL) {
   2.115 +        *_clickedIndex = (int) buttonIndex;
   2.116 +    }
   2.117  }
   2.118  
   2.119  @end
   2.120 +#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
   2.121  
   2.122 +static BOOL
   2.123 +UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   2.124 +{
   2.125 +    /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
   2.126 +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
   2.127 +    int i;
   2.128 +    int clickedindex = messageboxdata->numbuttons;
   2.129 +    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
   2.130 +    UIAlertView *alert = [[UIAlertView alloc] init];
   2.131 +    SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
   2.132  
   2.133 -SDL_bool
   2.134 -UIKit_ShowingMessageBox()
   2.135 -{
   2.136 -    return s_showingMessageBox;
   2.137 +    alert.delegate = delegate;
   2.138 +    alert.title = @(messageboxdata->title);
   2.139 +    alert.message = @(messageboxdata->message);
   2.140 +
   2.141 +    for (i = 0; i < messageboxdata->numbuttons; i++) {
   2.142 +        [alert addButtonWithTitle:@(buttons[i].text)];
   2.143 +    }
   2.144 +
   2.145 +    delegate.clickedIndex = &clickedindex;
   2.146 +
   2.147 +    [alert show];
   2.148 +
   2.149 +    UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
   2.150 +
   2.151 +    alert.delegate = nil;
   2.152 +
   2.153 +    *buttonid = messageboxdata->buttons[clickedindex].buttonid;
   2.154 +    return YES;
   2.155 +#else
   2.156 +    return NO;
   2.157 +#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
   2.158  }
   2.159  
   2.160  int
   2.161  UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   2.162  {
   2.163 -    int i;
   2.164 -    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
   2.165 +    BOOL success = NO;
   2.166  
   2.167      @autoreleasepool {
   2.168 -        UIAlertView *alert = [[UIAlertView alloc] init];
   2.169 -        SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
   2.170 +        success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
   2.171 +        if (!success) {
   2.172 +            success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
   2.173 +        }
   2.174 +    }
   2.175  
   2.176 -        alert.delegate = delegate;
   2.177 -        alert.title = @(messageboxdata->title);
   2.178 -        alert.message = @(messageboxdata->message);
   2.179 -
   2.180 -        for (i = 0; i < messageboxdata->numbuttons; ++i) {
   2.181 -            [alert addButtonWithTitle:@(buttons[i].text)];
   2.182 -        }
   2.183 -
   2.184 -        /* Set up for showing the alert */
   2.185 -        delegate.clickedIndex = messageboxdata->numbuttons;
   2.186 -
   2.187 -        [alert show];
   2.188 -
   2.189 -        /* Run the main event loop until the alert has finished */
   2.190 -        /* Note that this needs to be done on the main thread */
   2.191 -        s_showingMessageBox = SDL_TRUE;
   2.192 -        while (delegate.clickedIndex == messageboxdata->numbuttons) {
   2.193 -            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
   2.194 -        }
   2.195 -        s_showingMessageBox = SDL_FALSE;
   2.196 -
   2.197 -        *buttonid = messageboxdata->buttons[delegate.clickedIndex].buttonid;
   2.198 -
   2.199 -        alert.delegate = nil;
   2.200 +    if (!success) {
   2.201 +        return SDL_SetError("Could not show message box.");
   2.202      }
   2.203  
   2.204      return 0;
     3.1 --- a/src/video/uikit/SDL_uikitopengles.m	Mon Sep 21 21:19:37 2015 +0200
     3.2 +++ b/src/video/uikit/SDL_uikitopengles.m	Fri Sep 25 15:17:20 2015 -0300
     3.3 @@ -52,8 +52,6 @@
     3.4  
     3.5  @end
     3.6  
     3.7 -static int UIKit_GL_Initialize(_THIS);
     3.8 -
     3.9  void *
    3.10  UIKit_GL_GetProcAddress(_THIS, const char *proc)
    3.11  {
     4.1 --- a/src/video/uikit/SDL_uikitviewcontroller.h	Mon Sep 21 21:19:37 2015 +0200
     4.2 +++ b/src/video/uikit/SDL_uikitviewcontroller.h	Fri Sep 25 15:17:20 2015 -0300
     4.3 @@ -47,9 +47,7 @@
     4.4  - (void)loadView;
     4.5  - (void)viewDidLayoutSubviews;
     4.6  - (NSUInteger)supportedInterfaceOrientations;
     4.7 -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
     4.8  - (BOOL)prefersStatusBarHidden;
     4.9 -- (UIStatusBarStyle)preferredStatusBarStyle;
    4.10  
    4.11  #if SDL_IPHONE_KEYBOARD
    4.12  - (void)showKeyboard;
     5.1 --- a/src/video/uikit/SDL_uikitviewcontroller.m	Mon Sep 21 21:19:37 2015 +0200
     5.2 +++ b/src/video/uikit/SDL_uikitviewcontroller.m	Fri Sep 25 15:17:20 2015 -0300
     5.3 @@ -135,12 +135,6 @@
     5.4      return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
     5.5  }
     5.6  
     5.7 -- (UIStatusBarStyle)preferredStatusBarStyle
     5.8 -{
     5.9 -    /* We assume most SDL apps don't have a bright white background. */
    5.10 -    return UIStatusBarStyleLightContent;
    5.11 -}
    5.12 -
    5.13  /*
    5.14   ---- Keyboard related functionality below this line ----
    5.15   */