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.
Другие вопросы по тегам