Swift的UIApplication子类


91

在目标C中很简单:只需更新main.m文件并更改UIApplicationMain()参数即可

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

但是,由于该指南指出,因此没有main.m文件

“在全局范围内编写的代码被用作程序的入口点,因此您不需要主要功能。”

那么,如何快速将UIApplication子类化?有什么建议吗?


1
为什么最好更改UIApplicationMain()参数,NSPrincipalClass在app-info.plist 下添加类名?
2014年

Answers:


172

注意:如果您正在寻找以前的语法,请在2019年6月对XCode 10.1和Swift 5的语法进行了更新(此处提供了matt的答案,此处是Tung Fam的提供了答案)。

好,我找到了解决方案

首先,我注意到,在AppDelegate.swift文件的顶部,有这行

@UIApplicationMain

由于此行在任何范围之外(在文件级别),因此将立即执行,并且我假设编译器将其转换为标准的main函数。

因此,我从一个新的Swift-Only应用程序开始执行此操作:

  • 注释掉 @UIApplicationMain
  • 像这样添加了一个main.swift文件(FLApplication是我的子类)。
    重要文件必须命名为main.swift,因为其他文件不支持顶级语句!您不能在任何其他文件中添加UIApplicationMain()调用,否则将收到此错误:

不允许在顶层使用表达式

这是main.swift文件

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

然后,使用以下代码为UIApplication子类FLApplication.swift创建一个swift文件:

import UIKit
import Foundation

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

现在,UIApplication已正确子类化,您将在日志中看到“发送事件”消息


旧版本
供参考,由于此版本从版本1到版本3发生了很大变化,因此我将所有以前的编辑保留在此处


编辑-2015年3月

正如UIApplicationMain胡俊峰所评论的那样,有关和main.swift文件的说明已记录在《 Swift语言参考:链接》的 “属性”部分中。

如Thomas Verbeek所评论,在XCode 6.3 Beta中,您可能会发现C_ARGC和C_ARGV已分别重命名为Process.argc和Process.unsafeArgv。您在main.swift文件中的UIApplicationMain调用将需要更新为:

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

XCode 8之前的语法是

import Foundation
import UIKit

UIApplicationMain(C_ARGC, C_ARGV, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))

编辑-2016年12月

Beta 6之前的Xcode 8解决方案

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)
)

我试图了解是否可以在AppDelegate.swift文件中直接调用UIApplicationMain(),因为似乎此方法有“ Swift版本”,但是我遇到了编译器错误,我将做一些测试寻找“仅
速动

太酷了。我很好奇sendEvent:今天的重载用例是什么(我记得必须在iOS 3中使用它)
。– matt

2
万一有人想知道,UIApplicationMainmain.swift在The Swift Language Reference的Attributes部分中进行了说明。developer.apple.com/library/ios/documentation/Swift/Conceptual/...
hujunfeng

感谢您的提示,我99%确信在Swift手册的第一版中没有记录它:-)但是我将更新答案并添加您的信息。
LombaX 2015年

5
好答案。在XCode 6.3 Beta中,您可能会发现C_ARGCC_ARGV已经分别重命名为Process.argcProcess.unsafeArgv。您需要将main.swift文件中的UIApplicationMain调用更新为UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek

4

一种替代方法是扩展UIApplication而不是对其进行子类化。根据Apple发布的iBook,Swift中的扩展可以:

添加计算的属性和计算的静态属性定义实例方法和类型方法提供新的初始化程序定义下标定义和使用新的嵌套类型使现有类型符合协议

摘自:苹果公司。“快速编程语言。

如果UIApplication这些功能满足了您对子类的需求,那么可以采用扩展功能。


5
好的建议-不回答恕我直言:)
Daij-Djan

1
  1. 创建的子类UIApplication并添加逻辑

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
    
  2. 创建一个main.swift调用UIApplicationMain()全局函数[About]的文件,该文件是OS调用的应用程序的新入口点。该函数从被调用函数,UIApplication类名,UIApplicationDelegate类名接收参数,并启动主运行循环。

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
    
  3. 删除/注释@UIApplicationMain默认注释AppDelegate

    @UIApplicationMain产生main.swift

    如果您不这样做,将会得到一个编译错误:

    UIApplicationMain 属性不能在包含顶级代码的模块中使用

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.