Subclass UIApplication dengan Swift

92

Di Objective C itu sederhana: itu cukup untuk memperbarui file main.m dan mengubah parameter UIApplicationMain ()

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

Tetapi dengan cepat tidak ada file main.m, karena panduan mengatakan

"Kode yang ditulis pada cakupan global digunakan sebagai titik masuk untuk program, jadi Anda tidak memerlukan fungsi utama."

Lantas, bagaimana cara membuat subclass UIApplication dengan cepat ?? Ada saran?

LombaX
sumber
1
Mengapa lebih disukai untuk mengubah UIApplicationMain()parameter, untuk menambahkan nama kelas NSPrincipalClassdi bawah di app-info.plist?
Andreas

Jawaban:

173

CATATAN sintaks telah diperbarui untuk XCode 10.1 dan Swift 5 pada Juni 2019 (kredit untuk jawaban matt di sini && jawaban Tung Fam di sini ), jika Anda mencari sintaks sebelumnya, lihat bagian edit.

Oke, saya sudah menemukan solusinya

Pertama, saya perhatikan bahwa, di bagian atas file AppDelegate.swift, ada baris ini

@UIApplicationMain

Karena baris ini berada di luar cakupan apa pun (ada di level file), baris ini dijalankan segera, dan saya berasumsi bahwa kompilator menerjemahkannya dalam fungsi utama standar.

Jadi, saya melakukan ini, mulai dari aplikasi Swift-Only baru:

  • berkomentar @UIApplicationMain
  • menambahkan file main.swift seperti ini (FLApplication adalah subclass saya).
    PENTING file HARUS NAMA main.swift, karena pernyataan tingkat atas tidak didukung di file lain! Anda tidak dapat menambahkan panggilan UIApplicationMain () di dalam file lain, jika tidak, Anda akan menerima kesalahan ini:

Ekspresi tidak diperbolehkan di tingkat atas

Ini adalah file main.swift

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

Kemudian, buat file swift untuk subclass UIApplication, FLApplication.swift, dengan kode ini:

import UIKit
import Foundation

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

sekarang, UIApplication sudah di-subclass dengan benar dan Anda akan melihat pesan "send event" di log


EDIT LAMA
Untuk referensi, karena ini telah banyak berubah dari versi 1 ke versi 3, saya meninggalkan semua editan sebelumnya di sini


EDIT - MARET 2015

Seperti yang dikomentari oleh Hu Junfeng sekarang, penjelasan tentang UIApplicationMaindan file main.swift didokumentasikan di bagian Atribut Referensi Bahasa Swift: Tautan

Seperti yang dikomentari oleh Thomas Verbeek Dalam XCode 6.3 Beta, Anda mungkin menemukan bahwa C_ARGC dan C_ARGV telah diubah namanya menjadi Process.argc dan Process.unsafeArgv. Panggilan UIApplicationMain Anda di file main.swift perlu diperbarui ke:

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

Sintaks pra-XCode 8 adalah

import Foundation
import UIKit

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

EDIT - DES 2016

Solusi untuk Xcode 8, sebelum beta 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)
)
LombaX
sumber
Saya mencoba memahami apakah mungkin untuk memanggil UIApplicationMain () langsung di file AppDelegate.swift, karena tampaknya ada "versi cepat" dari metode ini, tetapi saya memiliki kesalahan kompiler, saya akan melakukan beberapa tes mencari solusi "hanya cepat"
LombaX
Sangat keren. Saya ingin tahu tentang kasus penggunaan apa untuk menimpa sendEvent:saat ini (saya ingat harus melakukannya di iOS 3 ...)
matt
2
Jika seseorang ingin tahu, UIApplicationMaindan main.swiftdidokumentasikan di bagian Atribut Referensi Bahasa Swift. developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng
Terima kasih atas petunjuknya, saya 99% yakin bahwa dalam rilis pertama manual Swift itu tidak didokumentasikan :-) namun saya akan memperbarui jawaban dengan menambahkan informasi Anda.
LombaX
5
Jawaban yang bagus. Di XCode 6.3 Beta, Anda mungkin menemukannya C_ARGCdan C_ARGVtelah diubah namanya menjadi Process.argcdan Process.unsafeArgvmasing - masing. Panggilan UIApplicationMain Anda di file main.swift perlu diperbarui keUIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek
4

Salah satu alternatifnya adalah dengan memperluas UIApplicationalih-alih membuat subkelasnya. Menurut iBook yang dirilis oleh Apple, ekstensi di Swift dapat:

Tambahkan properti komputasi dan properti statis terhitung Tentukan metode instans dan metode jenis Menyediakan penginisialisasi baru Tentukan langganan Tentukan dan gunakan jenis bertingkat baru Buat jenis yang ada sesuai dengan protokol

Kutipan Dari: Apple Inc. “Bahasa Pemrograman Cepat.

Jika kebutuhan Anda dalam subclass UIApplicationdipenuhi oleh kemampuan tersebut, Extension mungkin adalah cara yang tepat.

Cezar
sumber
5
saran yang bagus - jangan menjawab imho :)
Daij-Djan
1
  1. Buat subclass dari UIApplicationdan tambahkan logika Anda

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
    
  2. Buat main.swiftfile yang memanggil UIApplicationMain()fungsi global [About] , yang merupakan titik masuk baru dari aplikasi Anda yang dipanggil oleh OS. Fungsi ini menerima argumen dari fungsi yang dipanggil, UIApplicationnama UIApplicationDelegatekelas , nama kelas dan memulai run loop utama.

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
    
  3. Hapus / komentari @UIApplicationMainanotasi di default AppDelegate.

    @UIApplicationMainmenghasilkan main.swift.

    Jika tidak, Anda akan mendapatkan kesalahan kompilasi:

    UIApplicationMain atribut tidak dapat digunakan dalam modul yang berisi kode tingkat atas

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
    
yoAlex5
sumber