2016-08-03 41 views
6

Tôi biết có một số UncaughtExceptionHandler trong Cocoa, Tuy nhiên tôi cũng đang tìm kiếm điều tương tự cho Swift. tức là bất cứ khi nào có bất kỳ lỗi/ngoại lệ nào trong ứng dụng không được phát hiện cục bộ ở đó do bất kỳ sai lầm nào, nó sẽ bong bóng tất cả các cách tới đối tượng ứng dụng cấp cao nhất, nơi tôi có thể xử lý và xử lý người dùng một cách thích hợp.Lỗi không xử lý/Xử lý ngoại lệ trong Swift

Android có nó. Flex có nó. Java có nó. Tự hỏi tại sao Swift lại thiếu tính năng chính này.

+0

NSSetUncaughtExceptionHandler có sẵn là Swift: http://stackoverflow.com/questions/25441302/how-should-i-use-nssetuncaughtexceptionhandler-in-swift. Tuy nhiên, nó chỉ bắt ngoại lệ Objective-C, chứ không phải lỗi thời gian chạy Swift hoặc lỗi 'throw'n. –

+0

Cảm ơn @MartinR vì đã trả lời nhanh chóng của bạn. Tôi biết về NSSetUncaughtExceptionHandler rằng nó xử lý các trường hợp ngoại lệ của Objective-C. Tuy nhiên tôi đang tìm kiếm cùng một điều tương tự cho Swift. –

+0

Swift không có cơ chế để bắt tất cả các loại lỗi thời gian chạy. Tôi chỉ có thể đoán được lý do. Ví dụ, nó sẽ không hoạt động tốt với tính toán tham chiếu tự động. Bạn có thể nhận được phản hồi tốt hơn từ các nhà phát triển Swift trên một trong các danh sách gửi thư tại swift.org. –

Trả lời

8

Swift không có cơ chế để bắt tất cả ngoại lệ thời gian chạy tùy ý. Lý do được giải thích trong

trên nhanh chóng người dùng danh sách gửi thư. Giải nén:

Swift làm một sự lựa chọn có ý thức không bao gồm trường hợp ngoại lệ ném qua khung stack tùy ý không phải vì nó là về mặt kỹ thuật không thể, nhưng vì thiết kế của nó được đánh giá chi phí là quá cao.

Vấn đề là: nếu một đoạn mã sắp thoát sớm vì lỗi, nó phải được viết để xử lý lối thoát sớm đó. Nếu không nó sẽ hoạt động sai, không đóng được bộ nhớ, không đóng tập tin xử lý/ổ cắm/kết nối cơ sở dữ liệu/bất cứ điều gì, không giải phóng khóa, v.v. Trong một ngôn ngữ như Java, viết mã thực sự ngoại lệ an toàn yêu cầu số lượng vô lý thử/cuối cùng là khối. Đó là lý do tại sao không ai làm điều đó. Họ đưa ra các phán đoán về ngoại lệ nào mà họ đang xem là và tài nguyên nào nguy hiểm bị rò rỉ và chỉ bảo vệ mã của họ dựa trên các điều kiện dự đoán cụ thể đó. Sau đó, điều gì đó không lường trước được xảy ra và chương trình của họ bị gián đoạn.

này thậm chí còn tồi tệ hơn trong một ngôn ngữ tài liệu tham khảo-tính như Swift vì cân bằng đúng số lượng tài liệu tham khảo trong sự hiện diện của ngoại lệ cơ bản đòi hỏi mỗi chức năng để bao gồm tiềm ẩn khối finally để cân bằng tất cả các giữ lại đếm. Điều này có nghĩa là trình biên dịch phải tạo nhiều mã bổ sung trên cơ hội tắt mà một số cuộc gọi hoặc một trường hợp ngoại lệ khác. Phần lớn mã này không bao giờ, từng được sử dụng, nhưng nó phải ở đó, làm đầy quá trình này.

Vì những vấn đề này, Swift đã chọn không hỗ trợ các ngoại lệ truyền thống ; thay vào đó, nó chỉ cho phép bạn ném lỗi trong các khu vực mã đặc biệt được đánh dấu đặc biệt là . Nhưng như một hệ quả, điều đó có nghĩa rằng, nếu có điều gì đó thực sự sai trong mã mà không thể ném, tất cả nó có thể thực sự làm để ngăn ngừa thảm họa là sự cố. Và hiện tại, chỉ điều bạn có thể gặp phải là toàn bộ quá trình.

Để biết thêm thông tin, xem

+1

Cảm ơn @MartinR ... Tôi thấy rằng các chàng trai Swift đã giảm gánh nặng xử lý mọi ngoại lệ nhỏ hoặc lớn và lỗi cho các nhà phát triển "theo thiết kế". –

+1

Cảm ơn bạn rất nhiều vì đã chia sẻ, bây giờ ít nhất lý do là rõ ràng cho những gì có vẻ như một sự thiếu sót khó hiểu. – Crashalot

+2

Điều này là tốt với tôi, nhưng tôi vẫn cần ít nhất cũng có thể nắm bắt các tín hiệu để tôi có thể triển khai trình ghi lỗi. Có vẻ như không thể làm cho nó hoạt động được; force unwrapping nil ném một 'EXC_BAD_INSTRUCTION' mà tôi không thể bắt với bộ xử lý ngoại lệ hoặc tín hiệu ... –

5

Đây là mã tôi sử dụng để đăng nhập tất cả các trường hợp ngoại lệ/lỗi. Log.error(with:) là một chức năng tùy chỉnh nơi tôi lưu trữ theo dõi ngăn xếp, cùng với thông tin khác. Thread.callStackSymbols là một chuỗi các chuỗi và đại diện cho dấu vết ngăn xếp.

NSSetUncaughtExceptionHandler { (exception) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGABRT) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGILL) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGSEGV) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGFPE) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGBUS) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGPIPE) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
+0

Cảm ơn rất nhiều, thậm chí không biết về chức năng tín hiệu (...) –

+1

Lưu ý rằng chỉ" an toàn tín hiệu không đồng bộ "các hàm được an toàn để được gọi từ bên trong trình xử lý tín hiệu. "printf" và các chức năng liên quan không phải là tín hiệu không đồng bộ. –

+0

Bạn sử dụng mã này ở đâu? AppDelegate? chủ yếu? Tôi đã cố thêm mã này vào ứng dụng của mình mà không thành công. –