Xcode 8 beta 6: main.swift не скомпилируется
У нас есть собственный объект 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?
2 ответа
Я пишу это так:
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.
РЕДАКТИРОВАТЬ Эта проблема теперь решена в iOS 12 / Xcode 10. CommandLine.unsafeArgv
теперь имеет правильную подпись, и можно позвонить UIApplicationMain
без труда:
UIApplicationMain(
CommandLine.argc, CommandLine.unsafeArgv,
nil, NSStringFromClass(AppDelegate.self)
)
Похоже на то Process
был переименован в CommandLine
в бета 6.
Но тип 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))
}
(ОБНОВЛЕНИЕ) Это несоответствие следует рассматривать как ошибку. Как правило, вам лучше отправить отчет об ошибке, когда вы обнаружите, что "это не должно быть", например, третий параметр в бета-версии 5. Я надеюсь, что эта "ошибка" будет исправлена в ближайшее время.
Если вы просто хотите назначить свой пользовательский класс 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.