From 42cdbf6b214a4a4b614e6086d80bb12a1fce32be Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 12 Feb 2024 10:20:06 -0800 Subject: [PATCH] Explicitly retain and release NSObjects in C structures Fixes https://github.com/libsdl-org/SDL/issues/9021 Fixes https://github.com/libsdl-org/SDL/issues/9042 --- src/joystick/apple/SDL_mfijoystick.m | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index e33bd07079..e9f68e5930 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -498,7 +498,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle NSDictionary *elements = controller.physicalInputProfile.elements; /* Provide both axes and analog buttons as SDL axes */ - device->axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + NSArray *axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; @@ -513,8 +513,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->naxes = (int)device->axes.count; - device->buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + NSArray *buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; @@ -526,7 +525,12 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->nbuttons = (int)device->buttons.count; + /* Explicitly retain the arrays because SDL_JoystickDeviceItem is a + * struct, and ARC doesn't work with structs. */ + device->naxes = (int)axes.count; + device->axes = (__bridge NSArray *)CFBridgingRetain(axes); + device->nbuttons = (int)buttons.count; + device->buttons = (__bridge NSArray *)CFBridgingRetain(buttons); subtype = 4; #ifdef DEBUG_CONTROLLER_PROFILE @@ -750,13 +754,20 @@ static SDL_JoystickDeviceItem *IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem * #ifdef SDL_JOYSTICK_MFI @autoreleasepool { + /* These were explicitly retained in the struct, so they should be explicitly released before freeing the struct. */ if (device->controller) { - /* The controller was explicitly retained in the struct, so it - * should be explicitly released before freeing the struct. */ GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller)); controller.controllerPausedHandler = nil; device->controller = nil; } + if (device->axes) { + NSArray *axes = CFBridgingRelease((__bridge CFTypeRef)(device->axes)); + device->axes = nil; + } + if (device->buttons) { + NSArray *buttons = CFBridgingRelease((__bridge CFTypeRef)(device->buttons)); + device->buttons = nil; + } } #endif /* SDL_JOYSTICK_MFI */