26

Xin lỗi nếu câu hỏi này đã được trả lời ở một nơi khác, nhưng tôi không thể tìm thấy bất kỳ câu trả lời dứt khoát khi tìm kiếm trên nó:try-catch thực hành xử lý ngoại lệ dành cho iPhone/Objective-C

Tôi đang tự hỏi khi try- các khối catch sẽ được sử dụng trong các ứng dụng iPhone khách quan. "Giới thiệu về ngôn ngữ lập trình mục tiêu-C" của Apple nói rằng ngoại lệ là tài nguyên chuyên sâu và người ta không nên sử dụng các ngoại lệ cho kiểm soát luồng chung, hoặc đơn giản là để biểu thị lỗi. " Từ đọc một vài câu hỏi liên quan ở đây tôi cũng thu thập rằng mọi người thường không sử dụng phương pháp này trong thực tế. Vì vậy, tôi đoán câu hỏi là: các tình huống khi nào thích hợp để sử dụng các khối try-catch khi phát triển cho iPhone/Objective-C và khi nào thì chúng hoàn toàn KHÔNG được sử dụng? Các tính năng chính của nó là gì?

Ví dụ: tôi có thể sử dụng chúng để vượt quá giới hạn và các ngoại lệ khác khi làm việc với các đối tượng trong mảng. Tôi có một phương thức thực hiện vài nhiệm vụ với các đối tượng được truyền vào trong một số mảng. Phương thức trả về nil nếu một lỗi đã xảy ra và khối try-catch có thể giúp tôi nắm bắt các ngoại lệ. Tuy nhiên, tôi có thể tất nhiên chỉ cần viết ít thử nghiệm nếu ở đây và ở đó để đảm bảo rằng tôi, ví dụ, không bao giờ cố gắng truy cập vào một chỉ mục vượt quá giới hạn mảng. bạn sẽ làm gì trong tình huống này?

Cảm ơn rất nhiều!

+1

chấp nhận bất kỳ câu trả lời nào..về đăng câu trả lời của riêng bạn..Khác hơn 10 nghìn khách truy cập vẫn nhầm lẫn. –

+0

Xem câu trả lời hoàn chỉnh này http://stackoverflow.com/a/6802326/1845634 để biết các phương pháp hay nhất. – dazzli

Trả lời

28

Chỉ phù hợp khi sử dụng @ try/@ catch để xử lý các lỗi không thể khôi phục. Nó không bao giờ thích hợp để sử dụng @ throw/@ try/@ catch để làm điều khiển dòng chảy như hoạt động.

Cụ thể, nó sẽ không thích hợp để sử dụng để bắt ngoại lệ trừ khi mục tiêu của bạn là bắt chúng và bằng cách nào đó báo cáo lỗi, sau đó - thường - sự cố hoặc ít nhất, cảnh báo người dùng rằng ứng dụng của bạn ở trạng thái không nhất quán và có thể mất dữ liệu.

Hành vi của bất kỳ ngoại lệ nào được ném qua mã khung hệ thống là không xác định.

Kiểm tra nếu kiểm tra giới hạn của bạn là giải pháp thích hợp hơn nhiều.

19

câu trả lời của bbum là hoàn toàn chính xác (và anh ấy sẽ biết câu trả lời tốt hơn so với hầu hết). Để xây dựng một chút ...

Trong ca cao, bạn nên tránh sử dụng ngoại lệ (@try/@catch[/@finally]) để kiểm soát luồng. Như bạn đề cập, ngoại lệ mang một chi phí lớn bất thường (so với thời gian chạy như JVM hoặc CLR được tối ưu hóa để sử dụng ngoại lệ). Hơn nữa, hầu hết các khuôn khổ Cocoa không phải là ngoại lệ an toàn. Do đó, việc ném một ngoại lệ thông qua mã khuôn khổ Cocoa là nguy hiểm và có thể sẽ gây ra những lỗi kỳ lạ, khó chẩn đoán và thảm họa (nghĩ rằng có thể mất dữ liệu) trong ứng dụng của bạn.

Thay vì sử dụng ngoại lệ, mã ca cao sử dụng NSError để báo hiệu các điều kiện lỗi mà có thể khôi phục trong ứng dụng. Các ngoại lệ được sử dụng để báo hiệu các điều kiện mà từ đó ứng dụng của bạn không thể khôi phục được. Do đó một thành phần giao diện người dùng yêu cầu vị trí ngoài giới hạn trong một mảng mô hình có thể được báo hiệu bằng một lỗi (được trình bày cho người dùng với lý do yêu cầu của họ không thể hoàn thành) trong khi cố gắng truy cập vị trí ngoài giới hạn chỉ số mà bạn nghĩ rằng nên là hợp lệ tín hiệu một điều kiện đặc biệt, nơi bạn ứng dụng đang ở trong một nhà nước không phù hợp và có lẽ nên chết càng sớm càng tốt trước khi nó có thể làm thiệt hại nhiều hơn nữa.

NSParameterAssert, ví dụ: tín hiệu có số NSException khi xác nhận không thành công.

Vì vậy, khi nên bạn sử dụng ngoại lệ hoặc @try/@catch? Nếu bạn đang sử dụng một thư viện C/C++ sử dụng các ngoại lệ, bạn nên nắm bắt những ngoại lệ đó trước khi chúng có thể bị ném trở lại thông qua mã Cocoa. Tương tự, nếu bạn nghiêm túc về tính nhất quán của trạng thái trong ứng dụng của mình, bạn nên tăng ngoại lệ ngay sau khi bạn phát hiện rằng trạng thái của bạn không nhất quán (và không thể khôi phục).

+0

Hơn bạn để mở rộng. Cũng lưu ý rằng việc xác nhận và hủy bỏ() là bạn của bạn; chúng khiến ứng dụng gặp sự cố tại điểm hỏng hóc. Khi bạn @throw, bạn phải làm việc chăm chỉ để tái tạo lại chính xác nơi ứng dụng đã được tại thời điểm phát hiện bất thường. Thất bại sớm. Thất bại. – bbum

+0

Tôi không thấy cách NSError là một sự thay thế tốt cho cấu trúc try/catch kiểu Java. Toàn bộ ý tưởng là bạn không cần phải làm hỏng tất cả các mã ở hạ lưu chỉ để xử lý lỗi. Sử dụng NSError dường như đòi hỏi phải truyền nó xuống bất kỳ và tất cả các phương thức có thể gây ra lỗi. Xấu và dễ bị lỗi. Hacking nó với NSExceptions có thể là một điều tốt trong một số trường hợp. Và vâng, ngoại lệ rõ ràng chỉ dành cho trường hợp ngoại lệ, không phải cho những thứ bình thường, mong đợi. – n13

+1

Trường hợp ngoại lệ, một cách hiệu quả, một GOTO được giới hạn trong ngăn xếp của chuỗi hiện tại. Khi bạn @ ném, bạn GOTO một số khung tùy ý ở trên (một với @catch hoặc @ cuối cùng). Do đó, yêu cầu là rất nhiều - ngay cả khi đối mặt với thứ gì đó như GC - mọi phương thức được thực hiện ở mọi nơi đều phải ** luôn được chuẩn bị cho bất kỳ câu lệnh nào trong khung đó là câu lệnh cuối cùng được thực hiện (hoặc mọi phương thức phải thực hiện một @ cuối cùng). Kết quả cuối cùng là sự mong manh khối lượng, không hiệu quả và tăng kích thước mã. Nó cũng bay khi đối mặt với sự năng động của ObjC. – bbum