Cel-C: twierdzenie a wyjątek a błąd


79

W kakao, kiedy należy używać NSAssert, NSException, NSError?

Oto, o czym myślałem:

NSAssert - podczas tworzenia dowolnego programu klienckiego używanego dla własnych korzyści programistów w celu podwójnego sprawdzenia reguł, konwencji, założeń lub warunków wstępnych i końcowych?

NSException - podczas tworzenia biblioteki innej firmy na rzecz innych programistów, którzy korzystają z tej biblioteki, aby natychmiast wiedzieli, kiedy dane wejściowe są nieprawidłowe?

NSError - Podczas łączenia się z systemem zewnętrznym w celu uzyskania danych, takich jak plik, baza danych lub usługa sieciowa, które nie gwarantują uzyskania wyniku?

Odpowiedzi:


103

NSAssert rzuci wyjątek, gdy nie powiedzie się. NSAssert ma więc istnieć krótki i łatwy sposób pisania i sprawdzania wszelkich założeń, które poczyniłeś w swoim kodzie. To nie jest (moim zdaniem) alternatywa dla wyjątków, tylko skrót. Jeśli asercja się nie powiedzie, oznacza to, że coś poszło nie tak w twoim kodzie i program nie powinien kontynuować.

Należy zwrócić uwagę na to, że NSAssert nie zostanie wkompilowany do twojego kodu w kompilacji wydania, więc jest to zwykle używane do sprawdzania poprawności podczas programowania. Właściwie używam niestandardowego makra assert, które jest zawsze aktywne.

Czasy, w których chciałbyś @throwswój własny NSException, są wtedy, gdy zdecydowanie chcesz go w kompilacji wydania oraz w rzeczach, takich jak biblioteki publiczne / interfejs, gdy niektóre argumenty są nieprawidłowe lub zostałeś nieprawidłowo wywołany. Zauważ, że @catchwyjątek nie jest standardową praktyką i kontynuuj uruchamianie aplikacji. Jeśli spróbujesz tego z niektórymi standardowymi bibliotekami Apple (na przykład Core Data), mogą się zdarzyć złe rzeczy. Podobnie jak w przypadku potwierdzenia, jeśli zostanie zgłoszony wyjątek, aplikacja powinna zasadniczo zakończyć się dość szybko, ponieważ oznacza to, że gdzieś wystąpił błąd programowania.

NSErrors powinny być używane w twoich bibliotekach / interfejsach dla błędów, które nie są błędami programowania i które można odzyskać. Możesz podać informacje / kody błędów wywołującemu, który może obsłużyć błąd, w razie potrzeby powiadomić użytkownika i kontynuować wykonywanie. Zwykle dotyczy to takich rzeczy, jak błąd nieznalezienia pliku lub inny błąd niekrytyczny.


15
Mówiąc ściślej, nie należy używać NSException do wskazania możliwego do naprawienia błędu.
bbum

28
Innymi słowy: NSException == Javy w Obj-C i NSError == Javy w Obj-C. Brawo za konsekwencję!
Tustin2121,

2
Właściwie NSAssert zostanie wkompilowany w twój kod, jeśli nie dodasz NS_BLOCK_ASSERTIONS w prekompilowanych plikach prefiksów. Przeczytaj odpowiedź poniżej (po prostu zdobądź 50, aby pochwalić teraz :)
likid1412

3

Konwencja w kakao jest taka, że ​​wyjątek wskazuje na błąd programisty. Wiele kodu, w tym kod frameworka, nie jest zaprojektowanych do prawidłowego działania po zgłoszeniu wyjątku.

Każdy rodzaj błędu, który powinien być naprawiony, jest reprezentowany przez plik NSError. Istnieje również system prezentowania NSErrorplików użytkownikowi. Jak powiedziałeś, jest to szczególnie przydatne w przypadku omylnych zasobów zewnętrznych.

Pojęciowo, twierdzenie to stwierdzenie, że dany predykat zawsze daje wynik prawdziwy; jeśli tak nie jest, program jest uszkodzony. Chociaż jego zachowanie można modyfikować, NSAssertrodzina jest domyślnie wygodnym sposobem rzucania NSInternalInconsistencyExceptions (z opcją wyłączenia ich w kompilacjach wydań).


2

Edycja: w Xcode 4.2 potwierdzenia są domyślnie wyłączone dla kompilacji wydania,

Teraz NSAssert nie zostanie wkompilowany do twojego kodu w kompilacji wydania , ale możesz to zmienić w ustawieniach kompilacji


@Mike Weller, jedna odpowiedź jest błędna.

Należy zwrócić uwagę na to, że NSAssert nie zostanie wkompilowany do twojego kodu w kompilacji wydania , więc jest to zwykle używane do sprawdzania poprawności podczas programowania.

Właściwie NSAssert zostanie wkompilowany w twój kod, jeśli nie dodasz NS_BLOCK_ASSERTIONSprekompilowanych plików prefiksów.

W nocie technicznej TN2190 możemy znaleźć:

Makra, takie jak NDEBUG, aby wyłączyć C assert lub NS_BLOCK_ASSERTIONS, aby wyłączyć NSAssert Foundation, są ważne do określenia dla twoich wstępnie skompilowanych plików prefiksów

Lub możesz przeczytać ten: Jak sprawdzić, czy NSAssert jest wyłączony w kompilacjach wydań?


1

Ogólnie rzecz biorąc, wyjątki są używane do sygnalizowania błędów programisty - to rzeczy, które nie powinny się zdarzyć. Błędy są używane do sygnalizowania warunków błędów, które mogą wystąpić podczas normalnego działania programu - w zasadzie błędów użytkownika lub warunków zewnętrznych, które muszą być prawdziwe, ale mogą nie być. Zatem próba usunięcia zablokowanego elementu w dokumencie może być błędem, a próba pobrania pliku bez połączenia z Internetem byłaby błędem, ale próba uzyskania dostępu do nieprawidłowego elementu w kolekcji byłaby wyjątkiem.

Asercje są zwykle używane w testowaniu, a AFAIK nie są używane jako ogólny mechanizm obsługi błędów, jak inne.


Asercje mogą służyć do wymuszania niezmienników. Na przykład NSParameterAssert(someParam != nil);wymusi niezmiennik, że określony parametr nie może być zerowy.
Lily Ballard

@Kevin Ballard: Asercje są zwykle definiowane poza kompilacjami wydań, a przynajmniej były ostatnio sprawdzane, więc tak jak powiedziałem, nie są one ogólnym mechanizmem obsługi błędów.
Chuck

1
Mogą być, ale domyślnie nie są pomijane. Aby uzyskać takie zachowanie, musisz zmienić ustawienia kompilacji.
Lily Ballard,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.