Search code examples
ioscocoa-touchswift

Subclass UIApplication with Swift


In Objective C it was simple: it was sufficient to update the main.m file and change the UIApplicationMain() parameters

return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));

But in swift there is no main.m file, since the guide says

“Code written at global scope is used as the entry point for the program, so you don’t need a main function.”

So, how to subclass UIApplication in swift?? Any suggestion?


Solution

  • NOTE the syntax has been updated for XCode 10.1 and Swift 5 in Jun 2019 ( credits to matt's answer here && Tung Fam's answer here ), if you are looking for the previous syntaxes look at the edit section.

    Ok, I've found the solution

    First, I've noticed that, at the top of the AppDelegate.swift file, there is this line

    @UIApplicationMain
    

    Since this line is outside any scope (it's at file level), it's executed immediately, and I assume that the compiler translate it in a standard main function.

    So, I did this, starting from a new Swift-Only application:

    • commented out @UIApplicationMain
    • added a main.swift file like this (FLApplication is my subclass).
      IMPORTANT the file MUST BE NAMED main.swift, since top level statements are not supported on other files! You can't add the UIApplicationMain() call inside any other file, otherwise you'll receive this error:

    Expressions are not allowed at the top level

    This is the main.swift file

    UIApplicationMain(
        CommandLine.argc, CommandLine.unsafeArgv, 
        NSStringFromClass(FLApplication.self), NSStringFromClass(AppDelegate.self)
    )
    

    Then, create a swift file for the UIApplication subclass, FLApplication.swift, with this code:

    import UIKit
    import Foundation
    
    class FLApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
            print("send event")
        }
    }
    

    now, UIApplication is correctly subclassed and you'll see the "send event" messages in the log


    OLD EDITS
    For reference, since this has changed a lot from version 1 to version 3, I leave here all the previous edits


    EDIT - MARCH 2015

    As commented by Hu Junfeng now the explanations about UIApplicationMain and the main.swift file are documented in the Attributes section of The Swift Language Reference: Link

    As commented by Thomas Verbeek In the XCode 6.3 Beta, you might find that C_ARGC and C_ARGV have been renamed to Process.argc and Process.unsafeArgv respectively. Your UIApplicationMain call in the main.swift file will need updating to:

    UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))
    

    The pre-XCode 8 syntax was

    import Foundation
    import UIKit
    
    UIApplicationMain(C_ARGC, C_ARGV, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))
    

    EDIT - DEC 2016

    Solution for Xcode 8, before beta 6

    import Foundation
    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        UnsafeMutableRawPointer(CommandLine.unsafeArgv)
            .bindMemory( 
                to: UnsafeMutablePointer<Int8>.self, 
                capacity: Int(CommandLine.argc)),
        NSStringFromClass(FLApplication.self),
        NSStringFromClass(AppDelegate.self)
    )