【问题标题】:Xcode 8 beta 6: main.swift won't compileXcode 8 beta 6:main.swift 无法编译
【发布时间】:2016-12-29 13:25:41
【问题描述】:

我们有一个自定义 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 上,我们得到 Use of unresolved identifier 'Process'

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

【问题讨论】:

  • 我该如何指定 UIApplication 类?
  • 看来这个问题终于在 iOS 12 Xcode 10 中修复了。

标签: swift xcode main swift3 xcode8-beta6


【解决方案1】:

我是这样写的:

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

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

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

EDIT 这个问题现在在 Swift 4.2 中得到解决。 CommandLine.unsafeArgv 现在有了正确的签名,可以很容易地调用UIApplicationMain

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

【讨论】:

  • “CommandLine.unsafeArgv 现在具有正确的签名”可能会产生误导,它与旧 Swift 版本具有相同的签名。 UIApplicationMain 的签名已更改,argv 参数现在与 CommandLine.unsafeArgv 匹配。 – 无论如何,很高兴这个问题已经解决了。
  • 我收到了这个警告:'UIApplicationMain' is deprecated: Use the overload of UIApplicationMain where the type of the second parameter is UnsafeMutablePointer&lt;UnsafeMutablePointer&lt;Int8&gt;?&gt;, which is the same as the type of CommandLine.unsafeArgv.
【解决方案2】:

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

(更新)这种不匹配应该被视为一个错误。一般来说,当你发现“this-should-not-be”的东西时最好发送bug report,比如beta 5中的第三个参数。我希望这个“bug”能尽快修复。


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

NSPrincipalClass | String | $(PRODUCT_MODULE_NAME).MobileUIApplication

(在非原始键/值视图中显示为“主体类”。)

在您的 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.

【讨论】:

  • 请注意,这种情况被视为错误。这个答案或多或少与这里给出的答案相同:bugs.swift.org/browse/…
  • @matt ,我不认为告诉 Process 重命名为 CommandLine 与错误报告不同。但是,是的,似乎我的答案中的主要代码显示了该错误的解决方法,我将更新该部分。
  • @OOPer @matt 我可以在 iOS 应用程序的 Info.plist 中使用 NSPrincipleClass。但据我所知,它没有记录在案。这种方法更适合我的项目。
  • @Brad,它记录在标题文档中。 Cmd 单击UIApplicationMain。据我所知,iOS 8 SDK 对此进行了描述,并且结合了 iOS 版本 (8+) 以及我测试过的模拟器和设备(虽然不多),它运行良好。
  • @OOPer 终于想通了。在 Swift 中,用@objc(...) 标记 UIApplication 子类声明以赋予它一个未经处理的 Objective-C 名称是至关重要的。然后 NSPrincipalClass 工作。
猜你喜欢
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2016-12-27
  • 2017-01-10
  • 2014-11-03
相关资源
最近更新 更多