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 мы получаем Использование неразрешенного идентификатора "Процесс"

Что нам нужно сделать в Xcode 8 beta 6/Swift 3, чтобы определить UIApplicationMain?

Ответ 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.

РЕДАКТИРОВАТЬ Эта проблема теперь решена в Swift 4.2. CommandLine.unsafeArgv теперь имеет правильную подпись, и можно легко вызвать UIApplicationMain:

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

Ответ 2

Кажется, что Process было переименовано в CommandLine в бета-версии 6.

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

(ОБНОВЛЕНИЕ) Это несоответствие должно рассматриваться как ошибка. Как правило, вам лучше отправить отчет об ошибке , когда вы найдете вещи "этого не следует", например третий параметр в бета-версии 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.