return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));
但是在Swift中没有main.m文件,因为该指南说:
“在全局范围编写的代码用作程序的入口点,因此您不需要main函数。”
那么,如何在Swift中创建子类化UIApplication?有什么建议吗?
return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));
但是在Swift中没有main.m文件,因为该指南说:
“在全局范围编写的代码用作程序的入口点,因此您不需要main函数。”
那么,如何在Swift中创建子类化UIApplication?有什么建议吗?
@UIApplicationMain
由于此行位于任何范围之外(它在文件级别),因此会立即执行,我假设编译器将其转换为标准的main函数。
因此,我从一个新的仅Swift应用程序开始:
@UIApplicationMain
不允许在顶层使用表达式
这是main.swift文件
UIApplicationMain(
CommandLine.argc, CommandLine.unsafeArgv,
NSStringFromClass(FLApplication.self), NSStringFromClass(AppDelegate.self)
)
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月
Xcode 8的解决方案,在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)
)
UIApplicationMain
和main.swift
在Swift语言参考手册的属性部分有详细说明。https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html - JunfengC_ARGC
和 C_ARGV
已经被分别重命名为 Process.argc
和 Process.unsafeArgv
。因此,你需要更新 main.swift
文件中的 UIApplicationMain
调用,改为 UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
。 - Thomas VerbeekUIApplicationMain()
返回一个 Int32
。因此,难道不应该将其包装在 exit()
调用中,以便进程可以向操作系统报告其退出状态吗?就像 exit(UIApplicationMain(...))
一样。 - Eric Bakerexit()
的评论。UIApplicationMain()
的文档中说:“该函数永远不会返回。当用户退出 iOS 应用程序时...应用程序将移动到后台。”因此,似乎 iOS 正在“包装”启动的 iOS 应用程序进程,并忽略进程本来会终止的任何退出代码。 - Eric BakerUIApplication
而不是对其进行子类化。根据苹果发布的iBook,Swift中的扩展可以:
如果您在对添加计算属性和计算静态属性 定义实例方法和类型方法 提供新的初始化程序 定义下标 定义和使用新的嵌套类型 使现有类型符合协议
摘自:Apple Inc. “The Swift Programming Language.
UIApplication
进行子类化的需求已经满足了这些功能,则扩展可能是一个好的选择。Swift子类UIApplication
创建一个UIApplication
的子类,并添加你的逻辑
import UIKit
class CustomUIApplication: UIApplication {
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
}
}
创建一个main.swift
文件,调用UIApplicationMain()
全局函数[关于],这是你的应用程序的新入口点,由操作系统调用。该函数接收来自被调用函数的参数,包括UIApplication
类名、UIApplicationDelegate
类名,并启动主运行循环[关于]。
import UIKit
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(CustomUIApplication.self), //在步骤1中创建
NSStringFromClass(AppDelegate.self)
)
删除/注释默认的AppDelegate
上的@UIApplicationMain
注解。
@UIApplicationMain
会生成 main.swift
文件。
如果你不这样做,将会出现编译错误:
UIApplicationMain
属性不能在包含顶级代码的模块中使用。
//@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//...
}
UIApplicationMain()
参数更改为在app-info.plist下添加类名到NSPrincipalClass
会更可取? - Andreas