แอปพลิเคชั่น Subclass UIA กับ Swift


92

ใน Objective C นั้นง่ายมากเพียงแค่อัปเดตไฟล์ main.m และเปลี่ยนพารามิเตอร์ UIApplicationMain () ก็เพียงพอแล้ว

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

แต่อย่างรวดเร็วไม่มีไฟล์ main.m เนื่องจากคำแนะนำกล่าวว่า

“ โค้ดที่เขียนในขอบเขตส่วนกลางถูกใช้เป็นจุดเริ่มต้นของโปรแกรมดังนั้นคุณไม่จำเป็นต้องมีฟังก์ชันหลัก”

ดังนั้นวิธีการสมัคร UIA subclass อย่างรวดเร็ว ?? ข้อเสนอแนะใด ๆ ?


1
เหตุใดจึงควรเปลี่ยนUIApplicationMain()พารามิเตอร์เพิ่มชื่อคลาสด้านล่างNSPrincipalClassใน app-info.plist
Andreas

คำตอบ:


173

โปรดทราบว่าไวยากรณ์ได้รับการอัปเดตสำหรับ XCode 10.1 และ Swift 5 ในเดือนมิถุนายน 2019 (ให้เครดิตสำหรับคำตอบของ Matt ที่นี่ && 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 ฉันจึงปล่อยการแก้ไขก่อนหน้านี้ทั้งหมดไว้ที่นี่


แก้ไข - มีนาคม 2558

ตามความเห็นของ Hu Junfeng ตอนนี้คำอธิบายเกี่ยวกับUIApplicationMainและไฟล์ main.swift ได้รับการบันทึกไว้ในส่วนแอตทริบิวต์ของการอ้างอิงภาษา Swift: ลิงก์

ตามความเห็นของ Thomas Verbeek ใน XCode 6.3 Beta คุณอาจพบว่า 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))

แก้ไข - ธันวาคม 2559

โซลูชันสำหรับ 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บันทึกไว้ในส่วนแอตทริบิวต์ของการอ้างอิงภาษา Swift developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng

ขอบคุณสำหรับคำใบ้ฉันแน่ใจ 99% ว่าในคู่มือ Swift รุ่นแรกนั้นไม่มีเอกสาร :-) อย่างไรก็ตามฉันจะอัปเดตคำตอบโดยเพิ่มข้อมูลของคุณ
LombaX

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. “ ภาษาการเขียนโปรแกรม Swift

หากความต้องการของคุณในคลาสย่อย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. ลบ / แสดงความคิดเห็นคำอธิบายประกอบในการเริ่มต้น@UIApplicationMainAppDelegate

    @UIApplicationMainmain.swiftสร้าง

    หากคุณไม่ทำคุณจะได้รับข้อผิดพลาดในการคอมไพล์:

    UIApplicationMain ไม่สามารถใช้แอตทริบิวต์ในโมดูลที่มีรหัสระดับบนสุด

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
    
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.