SDL icon indicating copy to clipboard operation
SDL copied to clipboard

How to override SDLUIKitDelegate::getAppDelegateClassName?

Open irov opened this issue 2 years ago • 6 comments

There was a need to redefine a class "UIApplicationDelegate", what is the best way to do this? My searches have turned up nothing better than a code patch. If now there is no way without an intrusive way, is it possible to add "SDLUIKitDelegate" to the define which can be overridden in CMake. There was also an idea to add the class name parameter to "SDL_UIKitRunApp" and if it is not defined (equal to NULL), then take the default from getAppDelegateClassName.

Thanks, I hope I just didn't find a legal way to set the name :)

irov avatar Apr 02 '22 10:04 irov

Or add define SDL_APP_DELEGATE_CLASS_NAME

#ifndef SDL_APP_DELEGATE_CLASS_NAME
#define SDL_APP_DELEGATE_CLASS_NAME @"SDLUIKitDelegate"
#endif

+ (NSString *)getAppDelegateClassName
{
    /* subclassing notice: when you subclass this appdelegate, make sure to add
     * a category to override this method and return the actual name of the
     * delegate */
    return SDL_APP_DELEGATE_CLASS_NAME;
}

irov avatar Jun 12 '22 10:06 irov

you can achieve it with method swizzling:

#include <objc/runtime.h>

#define SDL_MAIN_HANDLED
#include <SDL2/SDL_main.h>

NSString *swizzled_getAppDelegateClassName(id __unused self, SEL __unused _cmd) {
    return NSStringFromClass([AppDelegate class]);
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        __auto_type method = class_getClassMethod(objc_getClass("SDLUIKitDelegate"), NSSelectorFromString(@"getAppDelegateClassName"));
        method_setImplementation(method, (IMP)swizzled_getAppDelegateClassName);
        return SDL_UIKitRunApp(argc, argv, SDL_main);
    }
}

I think it should also be possible without custom main function by performing swizzling in + (void)load in one of your objc classes.

kambala-decapitator avatar Aug 03 '22 10:08 kambala-decapitator

Yes, at first I tried to go this way and I kind of succeeded. But the patch on the SDL turned out to be very large. It's easier to replace 1 line. So I thought that it is worth the SDL to be able to specify this class name.

irov avatar Aug 03 '22 11:08 irov

But the patch on the SDL turned out to be very large

sorry, not sure what you mean, with the swizzling approach you don't need to patch SDL

kambala-decapitator avatar Aug 03 '22 11:08 kambala-decapitator

sorry, not sure what you mean, with the swizzling approach you don't need to patch SDL

Excuse me too, I didn't quite read your code correctly. Yes, I think that will work. But looks like a plan B.

irov avatar Aug 03 '22 11:08 irov

actually there is an easier way: simply don't call SDL_UIKitRunApp. Start iOS app normally via UIApplicationMain, then when ready, start SDL machinery:

SDL_SetMainReady();
SDL_iOSSetEventPump(SDL_TRUE);

// e.g. forward original args from NSProcessInfo.processInfo.arguments
// or just create argv manually from NSBundle.mainBundle.executablePath.fileSystemRepresentation
SDL_main(argc, argv);

SDL_iOSSetEventPump(SDL_FALSE);

this is the same as in https://github.com/libsdl-org/SDL/blob/main/src/video/uikit/SDL_uikitappdelegate.m#L347

kambala-decapitator avatar Aug 04 '22 08:08 kambala-decapitator

actually there is an easier way: simply don't call SDL_UIKitRunApp. Start iOS app normally via UIApplicationMain, then when ready, start SDL machinery:

SDL_SetMainReady();
SDL_iOSSetEventPump(SDL_TRUE);

// e.g. forward original args from NSProcessInfo.processInfo.arguments
// or just create argv manually from NSBundle.mainBundle.executablePath.fileSystemRepresentation
SDL_main(argc, argv);

SDL_iOSSetEventPump(SDL_FALSE);

this is the same as in https://github.com/libsdl-org/SDL/blob/main/src/video/uikit/SDL_uikitappdelegate.m#L347

That's quite a good solution. I'm looking forward to integrating SDL into a SwiftUI App. After setting up SDL, could you please tell me if SDL_main is similar to SDL_UIKitRunApp(Argc,Argv,SDL_main func)? Thanks.

Longtianmu avatar Oct 14 '23 15:10 Longtianmu

could you please tell me if SDL_main is similar to SDL_UIKitRunApp(Argc,Argv,SDL_main func)?

it is, as I see: https://github.com/libsdl-org/SDL/blob/95a9271dbfb2d1348ba8350ba608d9e6ff915bc1/include/SDL3/SDL_main_impl.h#L181-L184

kambala-decapitator avatar Oct 14 '23 15:10 kambala-decapitator

could you please tell me if SDL_main is similar to SDL_UIKitRunApp(Argc,Argv,SDL_main func)?

it is, as I see:

https://github.com/libsdl-org/SDL/blob/95a9271dbfb2d1348ba8350ba608d9e6ff915bc1/include/SDL3/SDL_main_impl.h#L181-L184

That actually works, except the SDL_iOSSetEventPump.

Longtianmu avatar Oct 14 '23 16:10 Longtianmu

SDL/include/SDL3/SDL_main_impl.h

And sadly I only receive a black screen with normal console log. I use

    SDL_SetMainReady();
    SDL_iPhoneSetEventPump(SDL_TRUE);
    launcher_main(argc, argv);
    SDL_iPhoneSetEventPump(SDL_FALSE);
    return 0;

To boot App in main.

Longtianmu avatar Oct 14 '23 18:10 Longtianmu