Subclass UIApplication with Swift
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)
)
Create a subclass of
UIApplication
and add your logicimport UIKit class CustomUIApplication: UIApplication { override func sendEvent(_ event: UIEvent) { super.sendEvent(event) } }
Create a
main.swift
file that calls theUIApplicationMain()
global function[About], which is the new entry point of your application that is called by the OS. This function receives argument from called function,UIApplication
class name,UIApplicationDelegate
class name and starts the main run loop.import UIKit UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(CustomUIApplication.self), //was created at step 1 NSStringFromClass(AppDelegate.self) )
Remove/comment the
@UIApplicationMain
annotation on the defaultAppDelegate
.@UIApplicationMain
generatesmain.swift
.If you don't you will get a compile error:
UIApplicationMain
attribute cannot be used in a module that contains top-level code//@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { //... }
One alternative is to extend UIApplication
instead of subclassing it. According to the iBook released by Apple, extensions in Swift can:
Add computed properties and computed static properties Define instance methods and type methods Provide new initializers Define subscripts Define and use new nested types Make an existing type conform to a protocol
Excerpt From: Apple Inc. “The Swift Programming Language.
If your needs in subclassing UIApplication
are satisfied by those capabilities, an Extension might be the way to go.