Jaki jest najlepszy sposób na zgłoszenie wyjątku w celu c / kakao?
objective-c
cocoa
exception-handling
Steph Thirion
źródło
źródło
@throw([NSException exceptionWith…])
podejścia, ponieważ jest bardziej zwięzły.Słowo ostrzeżenia tutaj. W Objective-C, w przeciwieństwie do wielu podobnych języków, na ogół powinieneś unikać stosowania wyjątków dla typowych sytuacji błędów, które mogą wystąpić podczas normalnej pracy.
Dokumentacja Apple dla Obj-C 2.0 stwierdza, co następuje: „Ważne: Wyjątki wymagają dużego zasobu w celu C. Nie należy używać wyjątków do ogólnej kontroli przepływu lub po prostu do oznaczania błędów (takich jak brak dostępu do pliku)”
Dokumentacja Apple dotycząca obsługi wyjątków pojęciowych wyjaśnia to samo, ale z większą ilością słów: „Ważne: powinieneś zarezerwować wyjątki w programowaniu lub nieoczekiwane błędy w czasie wykonywania, takie jak dostęp do kolekcji poza zakresem, próby mutacji niezmiennych obiektów, wysyłanie nieprawidłowej wiadomości i utrata połączenia z serwerem okien. Zazwyczaj zajmujesz się tego rodzaju błędami z wyjątkami, gdy tworzona jest aplikacja, a nie w środowisku wykonawczym. [.....] Zamiast wyjątków, obiekty błędów (NSError) i Mechanizm dostarczania błędów kakao to zalecany sposób komunikowania oczekiwanych błędów w aplikacjach kakaowych. ”
Powodem tego jest częściowo przestrzeganie idiomów programistycznych w Celu C (używanie zwracanych wartości w prostych przypadkach i parametry odniesienia (często klasa NSError) w bardziej złożonych przypadkach), częściowo dlatego, że zgłaszanie wyjątków jest znacznie droższe i wreszcie (i co najważniejsze), że wyjątki Objective-C są cienkim opakowaniem wokół funkcji setjmp () i longjmp () C, co zasadniczo psuje twoją ostrożną obsługę pamięci, zobacz to wyjaśnienie .
źródło
Xcode rozpoznaje
@throw
instrukcje jako punkty wyjścia funkcji, takie jakreturn
instrukcje. Użycie@throw
składni pozwala uniknąć błędnych ostrzeżeń „ Kontrola może osiągnąć koniec funkcji nieważnych ”, które możesz uzyskać[NSException raise:…]
.Ponadto
@throw
można go używać do rzucania obiektów, które nie należą do klasy NSException.źródło
Jeżeli chodzi
[NSException raise:format:]
. W przypadku osób wywodzących się ze środowiska Java przypomnisz sobie, że Java rozróżnia wyjątki od wyjątków RuntimeException. Wyjątek jest sprawdzonym wyjątkiem, a RuntimeException nie jest zaznaczone. W szczególności Java sugeruje stosowanie sprawdzonych wyjątków dla „normalnych warunków błędów” i niezaznaczonych wyjątków dla „błędów czasu wykonania spowodowanych błędem programisty”. Wygląda na to, że wyjątków Objective-C należy używać w tych samych miejscach, w których użyjesz niesprawdzonego wyjątku, a wartości zwracane przez kod błędu lub wartości NSError są preferowane w miejscach, w których użyjesz sprawdzonego wyjątku.źródło
Myślę, że aby zachować spójność, korzystniej jest używać @throw z własną klasą, która rozszerza NSException. Następnie używasz tych samych oznaczeń, aby w końcu spróbować złapać:
Apple wyjaśnia tutaj, jak zgłaszać i obsługiwać wyjątki: Łapanie wyjątków Zgłaszanie wyjątków
źródło
Od ObjC 2.0 wyjątki Objective-C nie są już opakowaniem dla setjmp () longjmp () C i są kompatybilne z wyjątkiem C ++, @try jest „bezpłatny”, ale rzucanie i łapanie wyjątków jest znacznie droższe.
W każdym razie, asercje (wykorzystujące rodzinę makr NSAssert i NSCAssert) rzucają NSException, i to rozsądne, aby używać ich jako stanów Ries.
źródło
Użyj NSError do komunikowania awarii zamiast wyjątków.
Szybkie punkty na temat NSError:
NSError pozwala kodom błędów w stylu C (liczbom całkowitym) jasno identyfikować główną przyczynę i, mam nadzieję, pozwolić programowi obsługi błędów na usunięcie błędu. Możesz bardzo łatwo zawijać kody błędów z bibliotek C, takich jak SQLite, w instancjach NSError.
NSError ma również tę zaletę, że jest obiektem i oferuje sposób bardziej szczegółowego opisania błędu za pomocą elementu słownika userInfo.
Ale co najlepsze, NSError NIE MOŻE zostać wyrzucony, dlatego zachęca do bardziej proaktywnego podejścia do obsługi błędów, w przeciwieństwie do innych języków, które po prostu rzucają gorącym ziemniakiem coraz dalej i dalej w górę stosu wywołań, w którym to momencie można go zgłosić tylko użytkownikowi i nie są traktowane w żaden znaczący sposób (nie, jeśli wierzysz w przestrzeganie największej zasady ukrywania informacji przez OOP).
Link referencyjny : referencja
źródło
Oto jak nauczyłem się tego z „Przewodnika po wielkim nerdach (wydanie 4)”:
źródło
userInfo:nil
. :)Możesz użyć dwóch metod zgłaszania wyjątku w bloku try catch
lub druga metoda
źródło
Uważam, że nigdy nie należy używać wyjątków do kontrolowania normalnego przebiegu programu. Ale należy zgłaszać wyjątki, gdy jakaś wartość nie pasuje do pożądanej wartości.
Na przykład, jeśli jakaś funkcja akceptuje wartość, a ta wartość nigdy nie może być zerowa, wtedy można wyśledzić wyjątek, zamiast próbować zrobić coś „inteligentnego” ...
Ries
źródło
Wyjątki powinieneś zgłaszać tylko wtedy, gdy znajdziesz się w sytuacji, która wskazuje na błąd programowania i chcesz zatrzymać działanie aplikacji. Dlatego najlepszym sposobem zgłaszania wyjątków jest użycie makr NSAssert i NSParameterAssert i upewnienie się, że NS_BLOCK_ASSERTIONS nie jest zdefiniowany.
źródło
Przykładowy kod przypadku: @throw ([wyjątek NSExceptionWithName: ...
}
Za pomocą:
Kolejny bardziej zaawansowany przypadek użycia:
}
źródło
Nie ma powodu, aby nie używać wyjątków zwykle w celu C, nawet w celu oznaczenia wyjątków od reguł biznesowych. Apple może powiedzieć NSError, kogo to obchodzi. Obj C istnieje już od dawna i kiedyś dokumentacja ALL C ++ powiedziała to samo. Powodem, dla którego nie ma znaczenia, jak drogie jest rzucanie i łapanie wyjątku, jest fakt, że czas jego trwania jest wyjątkowo krótki i ... jest to WYJĄTEK od normalnego przepływu. Nigdy w życiu nie słyszałam, żeby ktoś powiedział, że wyjątek ten wymagał dużo czasu, by zostać rzuconym i złapanym.
Są też ludzie, którzy uważają, że sam cel C jest zbyt drogi i zamiast tego koduje w C lub C ++. Mówienie, że zawsze używaj NSError, jest niedoinformowane i paranoiczne.
Ale pytanie o ten wątek nie zostało jeszcze wyjaśnione, jaki jest NAJLEPSZY sposób na zgłoszenie wyjątku. Sposoby zwrotu NSError są oczywiste.
Czy to jest: [NSException podwyżka: ... @throw [[Alokacja NSException] initWithName .... lub @ throw [[MyCustomException ...?
Używam tutaj zaznaczonej / niezaznaczonej reguły nieco inaczej niż powyżej.
Istotna różnica między (przy użyciu metafory Java) zaznaczonym / niezaznaczonym jest ważna -> czy można odzyskać od wyjątku. Przez odzyskiwanie rozumiem nie tylko nie awarię.
Używam więc niestandardowych klas wyjątków z @throw do wyjątków możliwych do odzyskania, ponieważ jest prawdopodobne, że będę miał metodę aplikacji, która szuka pewnych rodzajów awarii w wielu blokach @catch. Na przykład, jeśli moja aplikacja jest bankomatem, miałbym blok @catch dla „WithdrawalRequestExceedsBalanceException”.
Używam NSException: podwyżka dla wyjątków środowiska wykonawczego, ponieważ nie mam sposobu na odzyskanie od wyjątku, oprócz złapania go na wyższym poziomie i zarejestrowania go. I nie ma sensu tworzyć do tego niestandardowej klasy.
W każdym razie to właśnie robię, ale jeśli istnieje lepszy, równie wyrazisty sposób, chciałbym również wiedzieć. W moim własnym kodzie, odkąd już dawno przestałem kodować C hella, nigdy nie zwracam NSError, nawet jeśli przechodzę przez API.
źródło