Ứng dụng UIA lớp con với Swift


92

Trong Objective C, thật đơn giản: chỉ cần cập nhật tệp main.m và thay đổi các tham số UIApplicationMain () là đủ

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

Nhưng nhanh chóng không có tệp main.m, vì hướng dẫn cho biết

“Mã được viết ở phạm vi toàn cầu được sử dụng làm điểm đầu vào cho chương trình, vì vậy bạn không cần một hàm chính”.

Vì vậy, làm thế nào để phân lớp UIApplication trong nhanh chóng ?? Bất kì lời đề nghị nào?


1
Tại sao lại thích thay đổi UIApplicationMain()các tham số, thêm tên lớp NSPrincipalClassvào trong app-info.plist?
Andreas

Câu trả lời:


173

LƯU Ý cú pháp đã được cập nhật cho XCode 10.1 và Swift 5 vào tháng 6 năm 2019 (tín dụng cho câu trả lời của matt tại đây & câu trả lời của Tung Fam tại đây ), nếu bạn đang tìm kiếm các cú pháp trước đó, hãy xem phần chỉnh sửa.

Ok, tôi đã tìm ra giải pháp

Đầu tiên, tôi nhận thấy rằng, ở đầu tệp AppDelegate.swift, có dòng này

@UIApplicationMain

Vì dòng này nằm ngoài bất kỳ phạm vi nào (nó ở cấp tệp), nó được thực thi ngay lập tức và tôi giả sử rằng trình biên dịch dịch nó trong một hàm chính tiêu chuẩn.

Vì vậy, tôi đã làm điều này, bắt đầu từ một ứng dụng Swift-Only mới:

  • Bình luận @UIApplicationMain
  • đã thêm một tệp main.swift như thế này (FLApplication là lớp con của tôi).
    QUAN TRỌNG tệp PHẢI ĐƯỢC ĐẶT Tên là main.swift, vì các câu lệnh cấp cao nhất không được hỗ trợ trên các tệp khác! Bạn không thể thêm lệnh gọi UIApplicationMain () bên trong bất kỳ tệp nào khác, nếu không bạn sẽ gặp lỗi sau:

Biểu thức không được phép ở cấp cao nhất

Đây là tệp main.swift

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

Sau đó, tạo một tệp nhanh cho lớp con UIApplication, FLApplication.swift, với mã này:

import UIKit
import Foundation

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

bây giờ, Ứng dụng UIA được phân lớp chính xác và bạn sẽ thấy thông báo "gửi sự kiện" trong nhật ký


CÁC CHỈNH SỬA CŨ
Để tham khảo, vì cái này đã thay đổi rất nhiều từ phiên bản 1 đến phiên bản 3 nên tôi để lại đây tất cả các chỉnh sửa trước đó


CHỈNH SỬA - THÁNG 3 NĂM 2015

Như nhận xét của Hu Junfeng, bây giờ các giải thích về UIApplicationMainvà tệp main.swift được ghi lại trong phần Thuộc tính của Tài liệu tham khảo ngôn ngữ Swift: Liên kết

Như nhận xét của Thomas Verbeek Trong XCode 6.3 Beta, bạn có thể thấy rằng C_ARGC và C_ARGV đã được đổi tên lần lượt thành Process.argc và Process.unsafeArgv. Cuộc gọi UIApplicationMain của bạn trong tệp main.swift sẽ cần cập nhật thành:

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

Cú pháp trước XCode 8 là

import Foundation
import UIKit

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

EDIT - DEC 2016

Giải pháp cho Xcode 8, trước phiên bản 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)
)

Tôi đang cố gắng hiểu xem có thể gọi UIApplicationMain () trực tiếp trong tệp AppDelegate.swift hay không, vì có vẻ như có "phiên bản nhanh" của phương pháp này, nhưng tôi gặp lỗi trình biên dịch, tôi sẽ thực hiện một số kiểm tra tìm kiếm một "nhanh chóng chỉ" giải pháp
LombaX

Tuyệt vời. Tôi tò mò như những gì người sử dụng hợp cụ thể là cho trọng sendEvent:hiện nay (Tôi nhớ phải làm điều đó trong iOS 3 ...)
mờ

2
Trong trường hợp ai đó muốn biết, UIApplicationMainmain.swiftđược ghi lại trong phần Thuộc tính của Tham chiếu Ngôn ngữ Swift. developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng

Cảm ơn gợi ý, tôi chắc chắn 99% rằng trong bản phát hành đầu tiên của hướng dẫn sử dụng Swift, nó không được ghi lại :-) tuy nhiên tôi sẽ cập nhật câu trả lời bằng cách thêm thông tin của bạn.
LombaX

5
Câu trả lời chính xác. Trong XCode 6.3 Beta, bạn có thể thấy điều đó C_ARGCC_ARGVđã được đổi tên thành Process.argcProcess.unsafeArgvtương ứng. Gọi UIApplicationMain của bạn trong file main.swift sẽ cần cập nhật đểUIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek

4

Một thay thế là mở rộng UIApplicationthay vì phân lớp nó. Theo iBook do Apple phát hành, các tiện ích mở rộng trong Swift có thể:

Thêm thuộc tính được tính toán và thuộc tính tĩnh được tính toán Xác định phương thức thể hiện và phương thức kiểu Cung cấp trình khởi tạo mới Xác định chỉ số con Xác định và sử dụng kiểu lồng nhau mới Làm cho kiểu hiện có phù hợp với giao thức

Trích từ: Apple Inc. “Ngôn ngữ lập trình Swift.

Nếu nhu cầu của bạn trong phân lớp UIApplicationđược đáp ứng bởi những khả năng đó, thì một Tiện ích mở rộng có thể là cách để thực hiện.


5
đẹp tư vấn - không trả lời IMHO :)
Daij-Đan

1
  1. Tạo một lớp con UIApplicationvà thêm logic của bạn

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
    
  2. Tạo một main.swifttệp gọi UIApplicationMain()hàm chung [Giới thiệu] , là điểm nhập mới của ứng dụng của bạn được gọi bởi Hệ điều hành. Hàm này nhận đối số từ hàm được gọi, UIApplicationtên UIApplicationDelegatelớp , tên lớp và bắt đầu vòng lặp chạy chính.

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
    
  3. Xóa / bình luận @UIApplicationMainchú thích theo mặc định AppDelegate.

    @UIApplicationMaintạo ra main.swift.

    Nếu không, bạn sẽ gặp lỗi biên dịch:

    UIApplicationMain không thể sử dụng thuộc tính trong một mô-đun có chứa mã cấp cao nhất

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
    
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.