Підклас UIA Застосування за допомогою Swift


92

У цілі C це було просто: достатньо було оновити файл main.m та змінити параметри UIApplicationMain ()

return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));

Але в swift немає файлу main.m, оскільки керівництво каже

"Код, написаний у глобальному масштабі, використовується як точка входу в програму, тому вам не потрібна основна функція."

Отже, як швидко підклас UIAплікація ?? Будь-яка пропозиція?


1
Чому було б кращим змінити UIApplicationMain()параметри, додавши ім'я класу під NSPrincipalClassв app-info.plist?
Андреас

Відповіді:


173

ПРИМІТКА.Синтаксис оновлено для XCode 10.1 та Swift 5 у червні 2019 року (титри на відповідь Метта тут && відповідь Tung Fam тут ), якщо ви шукаєте попередні синтаксиси, дивіться у розділі редагування.

Гаразд, я знайшов рішення

По-перше, я помітив, що у верхній частині файлу AppDelegate.swift є цей рядок

@UIApplicationMain

Оскільки цей рядок знаходиться поза будь-якою сферою дії (він знаходиться на рівні файлу), він виконується негайно, і я припускаю, що компілятор перекладе його у стандартну основну функцію.

Отже, я зробив це, починаючи з нової програми Swift-Only:

  • прокоментував @UIApplicationMain
  • додав такий файл main.swift, як цей (FLApplication - мій підклас).
    ВАЖЛИВО файл МОЖЕ НАЗВАТИ main.swift, оскільки оператори верхнього рівня не підтримуються в інших файлах! Ви не можете додати виклик UIApplicationMain () всередині будь-якого іншого файлу, інакше ви отримаєте таку помилку:

Вирази заборонені на верхньому рівні

Це файл main.swift

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

Потім створіть швидкий файл для підкласу UIApplication, FLApplication.swift, з таким кодом:

import UIKit
import Foundation

class FLApplication: UIApplication {
    override func sendEvent(_ event: UIEvent) {
        super.sendEvent(event)
        print("send event")
    }
}

тепер UIApplication правильно підкласифіковано, і ви побачите повідомлення "відправити подію" в журналі


СТАРІ РЕДАКТИ
Для довідки, оскільки це сильно змінилося з версії 1 на версію 3, я залишаю тут усі попередні редагування


РЕДАКТУВАТИ - БЕРЕЗЕНЬ 2015

Як зауважив Ху Цзюньфен, пояснення щодо UIApplicationMainфайлу main.swift та документа main.swift задокументовані в розділі "Атрибути" Довідника мови Swift: Посилання

Як прокоментував Томас Вербек У бета-версії XCode 6.3, ви можете виявити, що C_ARGC та C_ARGV були перейменовані на Process.argc та Process.unsafeArgv відповідно. Ваш виклик UIApplicationMain у файлі main.swift потребуватиме оновлення до:

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

Синтаксис до XCode 8 був

import Foundation
import UIKit

UIApplicationMain(C_ARGC, C_ARGV, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))

РЕДАГУВАТИ - ГРУДЬ 2016

Рішення для Xcode 8, до бета-версії 6

import Foundation
import UIKit

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

Я намагаюся зрозуміти, чи можна викликати UIApplicationMain () безпосередньо у файлі AppDelegate.swift, оскільки здається, що існує "швидка версія" цього методу, але у мене є помилка компілятора, я проведу кілька тестів пошук "лише швидкого" рішення
LombaX

Неймовірно круто. Мені цікаво, яким є варіант використання для заміни в sendEvent:наш час (я пам’ятаю, що це потрібно було робити в iOS 3 ...)
мат,

2
На випадок, якщо хтось захоче знати, UIApplicationMainі main.swiftце задокументовано в розділі Атрибути Довідника про швидку мову. developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng 01

Дякую за підказку, я на 99% впевнений, що у першому випуску посібника Swift це не було задокументовано :-) однак я оновлю відповідь, додаючи вашу інформацію.
LombaX 02.03.15

5
Чудова відповідь. У XCode 6.3 Beta, ви можете виявити , що C_ARGCі C_ARGVбули перейменовані в Process.argcі Process.unsafeArgvвідповідно. Ваш основний дзвінок UIApplicationMain у файлі main.swift потребуватиме оновлення доUIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek

4

Однією з альтернатив є розширення, UIApplicationа не його підкласифікація. Згідно з iBook, випущеним Apple, розширення в Swift можуть:

Додавання обчислюваних властивостей та обчислюваних статичних властивостей Визначення методів екземпляра та методів типу Надання нових ініціалізаторів Визначення індексів Визначення та використання нових вкладених типів Зробити існуючий тип відповідним протоколу

Витяг від: Apple Inc. “Швидка мова програмування.

Якщо ваші можливості в підкласифікації UIApplicationзадовольняються цими можливостями, розширення може бути найкращим шляхом.


5
приємна порада - не відповідати imho :)
Daij-Djan

1
  1. Створіть підклас UIApplicationта додайте свою логіку

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
  2. Створіть main.swiftфайл, який викликає UIApplicationMain()глобальну функцію [About] , яка є новою точкою входу у вашу програму, що викликається ОС. Ця функція отримує аргумент від викликаної функції, UIApplicationімені UIApplicationDelegateкласу, імені класу і запускає основний цикл запуску.

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
  3. Видаліть / прокоментуйте @UIApplicationMainанотацію за замовчуванням AppDelegate.

    @UIApplicationMainгенерує main.swift.

    Якщо ви цього не зробите, ви отримаєте помилку компіляції:

    UIApplicationMain атрибут не можна використовувати в модулі, що містить код верхнього рівня

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.