[SDL3, iOS] - Adding a custom AppDelegate in Swift

I got SDL3 working on iOS with xcode, but in order to implement certain things I would need to have control over the app’s AppDelegate, similar to how on Android I have control over the main activity which just inherits from SDLActivity.

Is there a way to achieve this in SDL3 preferably using Swift rather than objc?

The best leads I have found so come from these posts but the way to go about it is still unclear to me:

Looking at SDL3’s AppDelegate (in src/video/uikit/SDL_uikitappdelegate.h), it looks like you do it the same way as mentioned in the first link:

  1. Create a class that inherits from SDLUIKitDelegate
  2. Add a category to SDLUIKitDelegate that overrides +(NSString *)getAppDelegateClassName to return the name of your subclass from #1

I know very little about Swift, but I know that it’s possible for Swift classes to inherit from Objective-C classes, so #1 is possible. As to whether or not you can add categories to Objective-C classes from Swift… :man_shrugging:

You could always create an Objective-C stub that calls your Swift code.

Thanks a lot for the tips @sjr.

I did manage to get it to work so I am posting here hoping others will find this useful.

After a bunch of experimentation this is what worked for me:

  1. Add the SDL sources to your include path so you can import "video/uikit/SDL_uikitappdelegate.h". You can do this the same way you add the SDL Public Headers to the include path as described in the SDL ios readme.

  2. Create a bridging header between swift and objc. This can just be a simpler header file that just does the following:

#ifndef SwiftObjcBridgingHeader_h
#define SwiftObjcBridgingHeader_h

#import "video/uikit/SDL_uikitappdelegate.h"

#endif /* SwiftObjcBridgingHeader_h */

After you create it, go to the “Build Settings” tab, search for “Objective-C Bridging Header” and set the path to your bridging header (e.g., YourProjectName/YourProjectName-Bridging-Header.h).

  1. Create a category in objc to pass on the name of your new app delegate. Here is how I wrote mine:
#import <Foundation/Foundation.h>

#import "video/uikit/SDL_uikitappdelegate.h"
#import "YourProject-Swift.h" // This is an xcode generated header so you can import swift classes in objc

@interface SDLUIKitDelegate (Extensions)

@end

@implementation SDLUIKitDelegate (Extensions)

+ (NSString *)getAppDelegateClassName {
    return NSStringFromClass([AppDelegate class]);
}

@end

I initially tried making this in swift and it didn’t work, but when I made it in objc it did. Given this is such trivial code I am ok with it being in objc but I wanted the AppDelegate to be in Swift since I am more experienced with that.

  1. Create your new AppDelegate.swift and implement it as such:
import OSLog
import Foundation
import UIKit

class AppDelegate : SDLUIKitDelegate
{
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
    {
        os_log("Calling from SWIFT")
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

You should see the message logged there in your console, or alternatively (and more importantly imo) you can put a breakpoint on it to confirm it works. Your SDL code should still run as normal after.

Initially I tried writing a whole new app delegate from scratch but that was annoying, just inheriting from SDLUIKitDelegate and overriding methods while being sure to call super.whatever works perfectly as far as I can tell right now.

If there are any observations about my technique or anyone needs some help with this let me know. I am glad that now I can write swift code and debug it in xcode for any native ios needs I may have.

Nice! Two things:

  1. Is video/uikit/SDL_uikitappdelegate.h not part of the public headers? If not then IMHO it should be.

  2. Your overridden didFinishLaunchingWithOptions:method should probably call super.didFinishLaunchingWithOptions: before doing any of its own work

  1. It’s not as far as I can tell, and yeah I agree it would kinda make sense for it to be public I feel.

  2. That makes sense, it’s not clear to me if it matters either way tho, seems to all work just fine.

Hopefully others find this useful. Maybe I can contribute adding some info about this to the SDL wiki or ios readme in the main repo since it seems useful for people who want to do platform specific stuff. From the little I’ve seen online a lot of people need this for things such as notifications and in SDL3 the method of doing this changed so such info is quite useful.