Subclass Uiapplication With Swift

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.self,
capacity: Int(CommandLine.argc)),
NSStringFromClass(FLApplication.self),
NSStringFromClass(AppDelegate.self)
)

How to access UIApplication subclass functions

According to docs:

Every iOS app has exactly one instance of UIApplication (or, very
rarely, a subclass of UIApplication). When an app is launched, the
system calls the UIApplicationMain(::::) function; among its other
tasks, this function creates a Singleton UIApplication object.
Thereafter you access the object by calling the shared class method.

So in MyVC you should be able to do CustomUIApplication.shared.startTimer().

Said that, may I suggest you to consider having a separate class for handling start/stop time functionality, instead of having a subclass of UIApplication? You can make your own singleton for that and access it from wherever you need in a similar way.

EDIT: Of course, you have to define static var shared: Self { UIApplication.shared as! Self } first. (Per @Sulthan's comment)

How to subclass UIApplication?

Did you pass the name of your subclass to UIApplicationMain? Let's assume you have

@interface MyUIApp : UIApplication 
...

then in main() you should do:

NSString* appClass = @"MyUIApp";
NSString* delegateClass = nil;
int retVal = UIApplicationMain(argc, argv, appClass, delegateClass);

Objective-C project with Swift UIApplication subclass. Error: class not loaded

Maybe that's because it uses NSStringFromClass or something, so that in Swift RMFApplication is "mangled" and becomes something like "somePrefix"RMFApplication (or whatever different from just "RMFApplication").

You could try this:

@objc(RMFApplication) class RMFApplication: UIApplication

And then NSStringFromClass will return just "RMFApplication".

Not sure how to properly subclass UIApplication while using storyboards

It sounds like you changed the wrong argument to UIApplicationMain.

The default call to UIApplicationMain looks like this:

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

The third argument (nil by default) is the name of the UIApplication class to use. If it's nil, the app just uses UIApplication.

The fourth argument is the name of the UIApplicationDelegate class to use.

It sounds like you changed the fourth argument, but you should have changed the third argument:

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


Related Topics



Leave a reply



Submit