Added missing autorelease pool blocks in UIKit backend code. Fixes memory leak issues, especially in SDL_video. iOS-improvements
authorAlex Szpakowski <slime73@gmail.com>
Tue, 29 Jul 2014 00:36:12 -0300
branchiOS-improvements
changeset 9506 18e3f94bd860
parent 9505 6fc615dfc93f
child 9507 b1e690e9c5b3
Added missing autorelease pool blocks in UIKit backend code. Fixes memory leak issues, especially in SDL_video.
src/joystick/iphoneos/SDL_sysjoystick.m
src/power/uikit/SDL_syspower.m
src/video/uikit/SDL_uikitmodes.m
src/video/uikit/SDL_uikitopengles.m
src/video/uikit/SDL_uikitview.m
src/video/uikit/SDL_uikitwindow.m
--- a/src/joystick/iphoneos/SDL_sysjoystick.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/joystick/iphoneos/SDL_sysjoystick.m	Tue Jul 29 00:36:12 2014 -0300
@@ -90,13 +90,15 @@
     joystick->nballs = 0;
     joystick->nbuttons = 0;
 
-    if (motionManager == nil) {
-        motionManager = [[CMMotionManager alloc] init];
-    }
+    @autoreleasepool {
+        if (motionManager == nil) {
+            motionManager = [[CMMotionManager alloc] init];
+        }
 
-    /* Shorter times between updates can significantly increase CPU usage. */
-    motionManager.accelerometerUpdateInterval = 0.1;
-    [motionManager startAccelerometerUpdates];
+        /* Shorter times between updates can significantly increase CPU usage. */
+        motionManager.accelerometerUpdateInterval = 0.1;
+        [motionManager startAccelerometerUpdates];
+    }
 
     return 0;
 }
@@ -113,12 +115,14 @@
     const SInt16 maxsint16 = 0x7FFF;
     CMAcceleration accel;
 
-    if (!motionManager.accelerometerActive) {
-        return;
+    @autoreleasepool {
+        if (!motionManager.accelerometerActive) {
+            return;
+        }
+
+        accel = motionManager.accelerometerData.acceleration;
     }
 
-    accel = [[motionManager accelerometerData] acceleration];
-
     /*
      Convert accelerometer data from floating point to Sint16, which is what
      the joystick system expects.
@@ -161,7 +165,9 @@
 void
 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 {
-    [motionManager stopAccelerometerUpdates];
+    @autoreleasepool {
+        [motionManager stopAccelerometerUpdates];
+    }
     joystick->closed = 1;
 }
 
@@ -169,9 +175,11 @@
 void
 SDL_SYS_JoystickQuit(void)
 {
-    if (motionManager != nil) {
-        [motionManager release];
-        motionManager = nil;
+    @autoreleasepool {
+        if (motionManager != nil) {
+            [motionManager release];
+            motionManager = nil;
+        }
     }
 
     numjoysticks = 0;
--- a/src/power/uikit/SDL_syspower.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/power/uikit/SDL_syspower.m	Tue Jul 29 00:36:12 2014 -0300
@@ -50,24 +50,24 @@
 SDL_bool
 SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
 {
-    UIDevice *uidev = [UIDevice currentDevice];
+    @autoreleasepool {
+        UIDevice *uidev = [UIDevice currentDevice];
 
-    if (!SDL_UIKitLastPowerInfoQuery) {
-        SDL_assert([uidev isBatteryMonitoringEnabled] == NO);
-        [uidev setBatteryMonitoringEnabled:YES];
-    }
+        if (!SDL_UIKitLastPowerInfoQuery) {
+            SDL_assert(uidev.isBatteryMonitoringEnabled == NO);
+            uidev.batteryMonitoringEnabled = YES;
+        }
 
-    /* UIKit_GL_SwapWindow() (etc) will check this and disable the battery
-     *  monitoring if the app hasn't queried it in the last X seconds.
-     *  Apparently monitoring the battery burns battery life.  :)
-     *  Apple's docs say not to monitor the battery unless you need it.
-     */
-    SDL_UIKitLastPowerInfoQuery = SDL_GetTicks();
+        /* UIKit_GL_SwapWindow() (etc) will check this and disable the battery
+         *  monitoring if the app hasn't queried it in the last X seconds.
+         *  Apparently monitoring the battery burns battery life.  :)
+         *  Apple's docs say not to monitor the battery unless you need it.
+         */
+        SDL_UIKitLastPowerInfoQuery = SDL_GetTicks();
 
-    *seconds = -1;   /* no API to estimate this in UIKit. */
+        *seconds = -1;   /* no API to estimate this in UIKit. */
 
-    switch ([uidev batteryState])
-    {
+        switch (uidev.batteryState) {
         case UIDeviceBatteryStateCharging:
             *state = SDL_POWERSTATE_CHARGING;
             break;
@@ -84,11 +84,12 @@
         default:
             *state = SDL_POWERSTATE_UNKNOWN;
             break;
-    }
+        }
 
-    const float level = [uidev batteryLevel];
-    *percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
-    return SDL_TRUE;            /* always the definitive answer on iOS. */
+        const float level = uidev.batteryLevel;
+        *percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
+        return SDL_TRUE; /* always the definitive answer on iOS. */
+    }
 }
 
 #endif /* SDL_POWER_UIKIT */
--- a/src/video/uikit/SDL_uikitmodes.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/video/uikit/SDL_uikitmodes.m	Tue Jul 29 00:36:12 2014 -0300
@@ -159,9 +159,11 @@
 int
 UIKit_InitModes(_THIS)
 {
-    for (UIScreen *uiscreen in [UIScreen screens]) {
-        if (UIKit_AddDisplay(uiscreen) < 0) {
-            return -1;
+    @autoreleasepool {
+        for (UIScreen *uiscreen in [UIScreen screens]) {
+            if (UIKit_AddDisplay(uiscreen) < 0) {
+                return -1;
+            }
         }
     }
 
@@ -173,26 +175,28 @@
 {
     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
 
-    SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen);
-    SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]);
-    CGFloat scale = data->uiscreen.scale;
+    @autoreleasepool {
+        SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen);
+        SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]);
+        CGFloat scale = data->uiscreen.scale;
 
-    for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
-        /* The size of a UIScreenMode is in pixels, but we deal exclusively in
-         * points (except in SDL_GL_GetDrawableSize.) */
-        CGSize size = [uimode size];
-        int w = (int)(size.width / scale);
-        int h = (int)(size.height / scale);
+        for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
+            /* The size of a UIScreenMode is in pixels, but we deal exclusively in
+             * points (except in SDL_GL_GetDrawableSize.) */
+            CGSize size = [uimode size];
+            int w = (int)(size.width / scale);
+            int h = (int)(size.height / scale);
 
-        /* Make sure the width/height are oriented correctly */
-        if (isLandscape != (w > h)) {
-            int tmp = w;
-            w = h;
-            h = tmp;
+            /* Make sure the width/height are oriented correctly */
+            if (isLandscape != (w > h)) {
+                int tmp = w;
+                w = h;
+                h = tmp;
+            }
+
+            /* Add the native screen resolution. */
+            UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
         }
-
-        /* Add the native screen resolution. */
-        UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
     }
 }
 
@@ -202,16 +206,18 @@
     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
     SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
 
-    [data->uiscreen setCurrentMode:modedata->uiscreenmode];
+    @autoreleasepool {
+        [data->uiscreen setCurrentMode:modedata->uiscreenmode];
 
-    if (data->uiscreen == [UIScreen mainScreen]) {
-        if (mode->w > mode->h) {
-            if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
-            }
-        } else if (mode->w < mode->h) {
-            if (UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
+        if (data->uiscreen == [UIScreen mainScreen]) {
+            if (mode->w > mode->h) {
+                if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
+                    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
+                }
+            } else if (mode->w < mode->h) {
+                if (UIKit_IsDisplayLandscape(data->uiscreen)) {
+                    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
+                }
             }
         }
     }
@@ -224,19 +230,21 @@
 {
     /* Release Objective-C objects, so higher level doesn't free() them. */
     int i, j;
-    for (i = 0; i < _this->num_displays; i++) {
-        SDL_VideoDisplay *display = &_this->displays[i];
+    @autoreleasepool {
+        for (i = 0; i < _this->num_displays; i++) {
+            SDL_VideoDisplay *display = &_this->displays[i];
 
-        UIKit_FreeDisplayModeData(&display->desktop_mode);
-        for (j = 0; j < display->num_display_modes; j++) {
-            SDL_DisplayMode *mode = &display->display_modes[j];
-            UIKit_FreeDisplayModeData(mode);
+            UIKit_FreeDisplayModeData(&display->desktop_mode);
+            for (j = 0; j < display->num_display_modes; j++) {
+                SDL_DisplayMode *mode = &display->display_modes[j];
+                UIKit_FreeDisplayModeData(mode);
+            }
+
+            SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+            [data->uiscreen release];
+            SDL_free(data);
+            display->driverdata = NULL;
         }
-
-        SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
-        [data->uiscreen release];
-        SDL_free(data);
-        display->driverdata = NULL;
     }
 }
 
--- a/src/video/uikit/SDL_uikitopengles.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/video/uikit/SDL_uikitopengles.m	Tue Jul 29 00:36:12 2014 -0300
@@ -52,12 +52,14 @@
 int
 UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
 {
-    if (context) {
-        SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
-        [data->view setCurrentContext];
-    }
-    else {
-        [EAGLContext setCurrentContext: nil];
+    @autoreleasepool {
+        if (context) {
+            SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+            [data->view setCurrentContext];
+        }
+        else {
+            [EAGLContext setCurrentContext: nil];
+        }
     }
 
     return 0;
@@ -67,11 +69,13 @@
 {
     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
 
-    if (w) {
-        *w = data->view.backingWidth;
-    }
-    if (h) {
-        *h = data->view.backingHeight;
+    @autoreleasepool {
+        if (w) {
+            *w = data->view.backingWidth;
+        }
+        if (h) {
+            *h = data->view.backingHeight;
+        }
     }
 }
 
@@ -92,106 +96,112 @@
 
 void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
 {
+    @autoreleasepool {
 #if SDL_POWER_UIKIT
-    /* Check once a frame to see if we should turn off the battery monitor. */
-    SDL_UIKit_UpdateBatteryMonitoring();
+        /* Check once a frame to see if we should turn off the battery monitor. */
+        SDL_UIKit_UpdateBatteryMonitoring();
 #endif
 
-    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+        SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
 
-    if (nil == data->view) {
-        return;
+        if (nil == data->view) {
+            return;
+        }
+        [data->view swapBuffers];
+
+        /* You need to pump events in order for the OS to make changes visible.
+           We don't pump events here because we don't want iOS application events
+           (low memory, terminate, etc.) to happen inside low level rendering.
+         */
     }
-    [data->view swapBuffers];
-
-    /* You need to pump events in order for the OS to make changes visible.
-       We don't pump events here because we don't want iOS application events
-       (low memory, terminate, etc.) to happen inside low level rendering.
-     */
 }
 
 SDL_GLContext
 UIKit_GL_CreateContext(_THIS, SDL_Window * window)
 {
-    SDL_uikitopenglview *view;
-    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-    UIWindow *uiwindow = data->uiwindow;
-    CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen);
-    EAGLSharegroup *share_group = nil;
-    CGFloat scale = 1.0;
+    @autoreleasepool {
+        SDL_uikitopenglview *view;
+        SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+        UIWindow *uiwindow = data->uiwindow;
+        CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen);
+        EAGLSharegroup *share_group = nil;
+        CGFloat scale = 1.0;
 
-    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
-        /* Set the scale to the natural scale factor of the screen - the backing
-           dimensions of the OpenGL view will match the pixel dimensions of the
-           screen rather than the dimensions in points.
-         */
-        scale = uiwindow.screen.scale;
-    }
+        if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+            /* Set the scale to the natural scale factor of the screen - the backing
+               dimensions of the OpenGL view will match the pixel dimensions of the
+               screen rather than the dimensions in points.
+             */
+            scale = uiwindow.screen.scale;
+        }
 
-    if (_this->gl_config.share_with_current_context) {
-        SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
-        share_group = [view.context sharegroup];
-    }
+        if (_this->gl_config.share_with_current_context) {
+            SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
+            share_group = [view.context sharegroup];
+        }
 
-    /* construct our view, passing in SDL's OpenGL configuration data */
-    view = [[SDL_uikitopenglview alloc] initWithFrame: frame
-                                                scale: scale
-                                        retainBacking: _this->gl_config.retained_backing
-                                                rBits: _this->gl_config.red_size
-                                                gBits: _this->gl_config.green_size
-                                                bBits: _this->gl_config.blue_size
-                                                aBits: _this->gl_config.alpha_size
-                                            depthBits: _this->gl_config.depth_size
-                                          stencilBits: _this->gl_config.stencil_size
-                                                 sRGB: _this->gl_config.framebuffer_srgb_capable
-                                         majorVersion: _this->gl_config.major_version
-                                           shareGroup: share_group];
-    if (!view) {
-        return NULL;
-    }
+        /* construct our view, passing in SDL's OpenGL configuration data */
+        view = [[SDL_uikitopenglview alloc] initWithFrame: frame
+                                                    scale: scale
+                                            retainBacking: _this->gl_config.retained_backing
+                                                    rBits: _this->gl_config.red_size
+                                                    gBits: _this->gl_config.green_size
+                                                    bBits: _this->gl_config.blue_size
+                                                    aBits: _this->gl_config.alpha_size
+                                                depthBits: _this->gl_config.depth_size
+                                              stencilBits: _this->gl_config.stencil_size
+                                                     sRGB: _this->gl_config.framebuffer_srgb_capable
+                                             majorVersion: _this->gl_config.major_version
+                                               shareGroup: share_group];
+        if (!view) {
+            return NULL;
+        }
 
-    data->view = view;
-    view->viewcontroller = data->viewcontroller;
-    if (view->viewcontroller != nil) {
-        [view->viewcontroller setView:view];
-        [view->viewcontroller retain];
-    }
-    [uiwindow addSubview: view];
+        data->view = view;
+        view->viewcontroller = data->viewcontroller;
+        if (view->viewcontroller != nil) {
+            [view->viewcontroller setView:view];
+            [view->viewcontroller retain];
+        }
+        [uiwindow addSubview: view];
 
-    /* The view controller needs to be the root in order to control rotation on iOS 6.0 */
-    if (uiwindow.rootViewController == nil) {
-        uiwindow.rootViewController = view->viewcontroller;
-    }
+        /* The view controller needs to be the root in order to control rotation on iOS 6.0 */
+        if (uiwindow.rootViewController == nil) {
+            uiwindow.rootViewController = view->viewcontroller;
+        }
 
-    if (UIKit_GL_MakeCurrent(_this, window, view) < 0) {
-        UIKit_GL_DeleteContext(_this, view);
-        return NULL;
-    }
+        if (UIKit_GL_MakeCurrent(_this, window, view) < 0) {
+            UIKit_GL_DeleteContext(_this, view);
+            return NULL;
+        }
 
-    /* Make this window the current mouse focus for touch input */
-    if (uiwindow.screen == [UIScreen mainScreen]) {
-        SDL_SetMouseFocus(window);
-        SDL_SetKeyboardFocus(window);
+        /* Make this window the current mouse focus for touch input */
+        if (uiwindow.screen == [UIScreen mainScreen]) {
+            SDL_SetMouseFocus(window);
+            SDL_SetKeyboardFocus(window);
+        }
+
+        return view;
     }
-
-    return view;
 }
 
 void
 UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
 {
-    /* the delegate has retained the view, this will release him */
-    SDL_uikitopenglview *view = (SDL_uikitopenglview *)context;
-    if (view->viewcontroller) {
-        UIWindow *uiwindow = (UIWindow *)view.superview;
-        if (uiwindow.rootViewController == view->viewcontroller) {
-            uiwindow.rootViewController = nil;
+    @autoreleasepool {
+        /* the delegate has retained the view, this will release him */
+        SDL_uikitopenglview *view = (SDL_uikitopenglview *)context;
+        if (view->viewcontroller) {
+            UIWindow *uiwindow = (UIWindow *)view.superview;
+            if (uiwindow.rootViewController == view->viewcontroller) {
+                uiwindow.rootViewController = nil;
+            }
+            [view->viewcontroller setView:nil];
+            [view->viewcontroller release];
         }
-        [view->viewcontroller setView:nil];
-        [view->viewcontroller release];
+        [view removeFromSuperview];
+        [view release];
     }
-    [view removeFromSuperview];
-    [view release];
 }
 
 #endif /* SDL_VIDEO_DRIVER_UIKIT */
--- a/src/video/uikit/SDL_uikitview.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/video/uikit/SDL_uikitview.m	Tue Jul 29 00:36:12 2014 -0300
@@ -318,28 +318,34 @@
 
 void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
 {
-    SDL_uikitview *view = getWindowView(window);
-    if (view != nil) {
-        [view showKeyboard];
+    @autoreleasepool {
+        SDL_uikitview *view = getWindowView(window);
+        if (view != nil) {
+            [view showKeyboard];
+        }
     }
 }
 
 void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
 {
-    SDL_uikitview *view = getWindowView(window);
-    if (view != nil) {
-        [view hideKeyboard];
+    @autoreleasepool {
+        SDL_uikitview *view = getWindowView(window);
+        if (view != nil) {
+            [view hideKeyboard];
+        }
     }
 }
 
 SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
 {
-    SDL_uikitview *view = getWindowView(window);
-    if (view == nil) {
-        return 0;
+    @autoreleasepool {
+        SDL_uikitview *view = getWindowView(window);
+        if (view == nil) {
+            return 0;
+        }
+
+        return view.isKeyboardVisible;
     }
-
-    return view.isKeyboardVisible;
 }
 
 
@@ -423,13 +429,15 @@
         SDL_InvalidParamError("rect");
         return;
     }
-    
-    SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
-    if (view == nil) {
-        return ;
+
+    @autoreleasepool {
+        SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
+        if (view == nil) {
+            return;
+        }
+
+        view.textInputRect = *rect;
     }
-
-    view.textInputRect = *rect;
 }
 
 
--- a/src/video/uikit/SDL_uikitwindow.m	Tue Jul 29 00:05:48 2014 -0300
+++ b/src/video/uikit/SDL_uikitwindow.m	Tue Jul 29 00:36:12 2014 -0300
@@ -132,84 +132,86 @@
 int
 UIKit_CreateWindow(_THIS, SDL_Window *window)
 {
-    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
-    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
-    const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
-    const CGSize origsize = [[data->uiscreen currentMode] size];
-
-    /* SDL currently puts this window at the start of display's linked list. We rely on this. */
-    SDL_assert(_this->windows == window);
-
-    /* We currently only handle a single window per display on iOS */
-    if (window->next != NULL) {
-        return SDL_SetError("Only one window allowed per display.");
-    }
+    @autoreleasepool {
+        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+        SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+        const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
+        const CGSize origsize = [[data->uiscreen currentMode] size];
 
-    /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
-     * user, so it's in standby), try to force the display to a resolution
-     * that most closely matches the desired window size.
-     */
-    if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
-        if (display->num_display_modes == 0) {
-            _this->GetDisplayModes(_this, display);
-        }
+        /* SDL currently puts this window at the start of display's linked list. We rely on this. */
+        SDL_assert(_this->windows == window);
 
-        int i;
-        const SDL_DisplayMode *bestmode = NULL;
-        for (i = display->num_display_modes; i >= 0; i--) {
-            const SDL_DisplayMode *mode = &display->display_modes[i];
-            if ((mode->w >= window->w) && (mode->h >= window->h))
-                bestmode = mode;
+        /* We currently only handle a single window per display on iOS */
+        if (window->next != NULL) {
+            return SDL_SetError("Only one window allowed per display.");
         }
 
-        if (bestmode) {
-            SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
-            [data->uiscreen setCurrentMode:modedata->uiscreenmode];
-
-            /* desktop_mode doesn't change here (the higher level will
-             * use it to set all the screens back to their defaults
-             * upon window destruction, SDL_Quit(), etc.
-             */
-            display->current_mode = *bestmode;
-        }
-    }
+        /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
+         * user, so it's in standby), try to force the display to a resolution
+         * that most closely matches the desired window size.
+         */
+        if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
+            if (display->num_display_modes == 0) {
+                _this->GetDisplayModes(_this, display);
+            }
 
-    if (data->uiscreen == [UIScreen mainScreen]) {
-        if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
-            [UIApplication sharedApplication].statusBarHidden = YES;
-        } else {
-            [UIApplication sharedApplication].statusBarHidden = NO;
-        }
-    }
+            int i;
+            const SDL_DisplayMode *bestmode = NULL;
+            for (i = display->num_display_modes; i >= 0; i--) {
+                const SDL_DisplayMode *mode = &display->display_modes[i];
+                if ((mode->w >= window->w) && (mode->h >= window->h))
+                    bestmode = mode;
+            }
 
-    if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
-        if (window->w > window->h) {
-            if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
-            }
-        } else if (window->w < window->h) {
-            if (UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
+            if (bestmode) {
+                SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
+                [data->uiscreen setCurrentMode:modedata->uiscreenmode];
+
+                /* desktop_mode doesn't change here (the higher level will
+                 * use it to set all the screens back to their defaults
+                 * upon window destruction, SDL_Quit(), etc.
+                 */
+                display->current_mode = *bestmode;
             }
         }
-    }
 
-    /* ignore the size user requested, and make a fullscreen window */
-    /* !!! FIXME: can we have a smaller view? */
-    SDL_uikitwindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data->uiscreen.bounds];
+        if (data->uiscreen == [UIScreen mainScreen]) {
+            if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
+                [UIApplication sharedApplication].statusBarHidden = YES;
+            } else {
+                [UIApplication sharedApplication].statusBarHidden = NO;
+            }
+        }
 
-    /* put the window on an external display if appropriate. This implicitly
-     * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
-     * main display, where we land by default, as that would eat the
-     * status bar real estate.
-     */
-    if (external) {
-        [uiwindow setScreen:data->uiscreen];
-    }
+        if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
+            if (window->w > window->h) {
+                if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
+                    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
+                }
+            } else if (window->w < window->h) {
+                if (UIKit_IsDisplayLandscape(data->uiscreen)) {
+                    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
+                }
+            }
+        }
 
-    if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
-        [uiwindow release];
-        return -1;
+        /* ignore the size user requested, and make a fullscreen window */
+        /* !!! FIXME: can we have a smaller view? */
+        SDL_uikitwindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data->uiscreen.bounds];
+
+        /* put the window on an external display if appropriate. This implicitly
+         * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
+         * main display, where we land by default, as that would eat the
+         * status bar real estate.
+         */
+        if (external) {
+            [uiwindow setScreen:data->uiscreen];
+        }
+
+        if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
+            [uiwindow release];
+            return -1;
+        }
     }
 
     return 1;
@@ -218,17 +220,21 @@
 void
 UIKit_ShowWindow(_THIS, SDL_Window * window)
 {
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    @autoreleasepool {
+        UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
 
-    [uiwindow makeKeyAndVisible];
+        [uiwindow makeKeyAndVisible];
+    }
 }
 
 void
 UIKit_HideWindow(_THIS, SDL_Window * window)
 {
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    @autoreleasepool {
+        UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
 
-    uiwindow.hidden = YES;
+        uiwindow.hidden = YES;
+    }
 }
 
 void
@@ -286,13 +292,17 @@
 void
 UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
 {
-    UIKit_UpdateWindowBorder(_this, window);
+    @autoreleasepool {
+        UIKit_UpdateWindowBorder(_this, window);
+    }
 }
 
 void
 UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
 {
-    UIKit_UpdateWindowBorder(_this, window);
+    @autoreleasepool {
+        UIKit_UpdateWindowBorder(_this, window);
+    }
 }
 
 void
@@ -300,27 +310,32 @@
 {
     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
 
-    if (data) {
-        [data->viewcontroller release];
-        [data->uiwindow release];
-        SDL_free(data);
+    @autoreleasepool {
+        if (data) {
+            [data->viewcontroller release];
+            [data->uiwindow release];
+            SDL_free(data);
+        }
     }
+
     window->driverdata = NULL;
 }
 
 SDL_bool
 UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
 {
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    @autoreleasepool {
+        UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
 
-    if (info->version.major <= SDL_MAJOR_VERSION) {
-        info->subsystem = SDL_SYSWM_UIKIT;
-        info->info.uikit.window = uiwindow;
-        return SDL_TRUE;
-    } else {
-        SDL_SetError("Application not compiled with SDL %d.%d\n",
-                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
-        return SDL_FALSE;
+        if (info->version.major <= SDL_MAJOR_VERSION) {
+            info->subsystem = SDL_SYSWM_UIKIT;
+            info->info.uikit.window = uiwindow;
+            return SDL_TRUE;
+        } else {
+            SDL_SetError("Application not compiled with SDL %d.%d\n",
+                         SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+            return SDL_FALSE;
+        }
     }
 }
 
@@ -333,7 +348,10 @@
         return SDL_SetError("Invalid window or view not set");
     }
 
-    [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
+    @autoreleasepool {
+        [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
+    }
+
     return 0;
 }