Xcode 8 beta 6:main.swift无法编译

23

我们有一个自定义的UIApplication对象,因此我们的main.swift文件是:

import Foundation
import UIKit

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

但这在Xcode 8 beta 5中无效,因此我们使用了以下方法

//TODO Swift 3 workaround? https://forums.developer.apple.com/thread/46405
UIApplicationMain( Process.argc, UnsafeMutablePointer<UnsafeMutablePointer<CChar>>(Process.unsafeArgv), nil, NSStringFromClass(AppDelegate.self))

在Xcode 8 beta 6中,我们遇到了未解决的标识符“Process”错误。

在Xcode 8 beta 6/Swift 3中,我们需要做什么来定义UIApplicationMain?


我该如何指定UIApplication类呢? - Jason Hocker
看起来这个问题终于在iOS 12 Xcode 10中得到了解决。 - matt
2个回答

60

我会这样写:

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

要更改UIApplication类,请在该公式中将nil替换为NSStringFromClass(MobileUIApplication.self)

但是,如果您的唯一目的是将UIApplication子类替换为共享应用程序实例,则有一种更简单的方法:在Info.plist中,添加“Principal class”键,并将其值设置为您的UIApplication子类的字符串名称,并使用一个 @objc(...)属性标记该子类的声明,使其具有相同的Objective-C名称。

编辑 此问题现在在Swift 4.2中已解决。 CommandLine.unsafeArgv现在具有正确的签名,可以轻松调用UIApplicationMain

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

2
“CommandLine.unsafeArgv现在具有正确的签名”可能会让人产生误解,它与旧版Swift中的签名相同。UIApplicationMain的签名已更改,argv参数现在与CommandLine.unsafeArgv匹配。- 无论如何,很高兴这个问题已经被解决了。 - Martin R
3
我收到了这个警告:'UIApplicationMain'已过时:使用重载的UIApplicationMain,其中第二个参数的类型是UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>,与CommandLine.unsafeArgv的类型相同。 - Hemang

5

在beta 6中,Process似乎已被更名为CommandLine

CommandLine

但是,CommandLine.unsafeArgv的类型与UIApplication的第二个参数不匹配,因此您可能需要编写类似以下内容的代码:

CommandLine.unsafeArgv.withMemoryRebound(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc)) {argv in
    _ = UIApplicationMain(CommandLine.argc, argv, NSStringFromClass(MobileUIApplication.self), NSStringFromClass(AppDelegate.self))
}

(更新)这种不匹配应该被视为一个bug。通常情况下,当你发现像beta 5中的第三个参数这样的“不应该出现”的问题时,最好发送一个bug报告。我希望这个“bug”能够很快得到修复。


如果你只是想指定自定义的UIApplication类,为什么不使用Info.plist呢?

NSPrincipalClass | String | $(PRODUCT_MODULE_NAME).MobileUIApplication

(在非原始键/值视图中显示为“Principal class”.)

将此内容添加到您的Info.plist文件中,您可以使用MobileUIApplication以正常方式使用@UIApplicationMain

(附加) UIApplicationMain的头文件文档:

// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no
// NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init.

请注意,此情况被视为错误。这个答案与此处给出的答案几乎完全相同:https://bugs.swift.org/browse/SR-1390?focusedCommentId=17441&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17441 - matt
@matt,我认为告诉Process被重命名为CommandLine并不等同于错误报告。但是,是的,我的答案中似乎主要代码展示了对该错误的解决方法,我会更新这部分内容。 - OOPer
@Brad,这在头文件文档中有记录。Cmd + 单击 UIApplicationMain。据我所知,iOS 8 SDK 对此进行了描述,并且我已经测试了所有 iOS 版本(8+)和模拟器以及设备的组合(虽然不多),它都可以正常工作。 - OOPer
@OOPer 也许有时候名称会被混淆,而有时则不会。但在我的新测试中,如果我们使用带有名称的 @objc(...),例如 @objc(MyApplication) class MyApplication,它总是有效的。 - matt
@matt,这种情况可能会发生。一个小的0.0.1版本更新或其他任何事情都可能会产生影响。目前,我们需要期望您的“始终如一”始终适用于我们的应用程序。 - OOPer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接