2016-08-03 15 views
6

Wiem, że w kakao jest UncaughtExceptionHandler, ale szukam tego samego dla Swift. to znaczy, gdy wystąpi jakikolwiek błąd/wyjątek w aplikacji, który nie zostanie tu złapany lokalnie z powodu jakiejkolwiek pomyłki, powinien zostać przesłodzony do obiektu aplikacji najwyższego poziomu, w którym powinienem móc z wdziękiem go obsłużyć i odpowiednio zareagować na użytkownika.Niepowodzenie Błąd/obsługa wyjątków w Swift

Android ma to. Flex ma to. Java ma to. Zastanawiasz się, dlaczego Swiftowi brakuje tej kluczowej funkcji.

+0

NSSetUncaughtExceptionHandler dostępna jest Swift: http://stackoverflow.com/questions/25441302/how-should-i-use-nssetuncaughtexceptionhandler-in-swift. Jednak przechwytuje tylko wyjątki w Objective-C, a nie Swiftowe błędy środowiska wykonawczego lub 'throw'n błędy. –

+0

Dzięki @MartinR za szybką odpowiedź. Wiem o NSSetUncaughtExceptionHandler, że obsługuje wyjątki Cel-C. Jednak szukam tego samego/podobnego dla Swift. –

+0

Swift nie ma mechanizmu przechwytywania wszystkich rodzajów błędów środowiska wykonawczego. Mogę tylko zgadywać o przyczynie. Na przykład nie działa dobrze z automatycznym liczeniem odwołań. Możesz uzyskać lepszą odpowiedź od twórców Swift na jednej z list mailingowych na swift.org. –

Odpowiedz

8

Swift nie ma mechanizmu przechwytywania wszystkich arbitralnych wyjątków w czasie wykonywania. Powody są wyjaśnione w

sprawie szybkiej użytkowników listy. Wyciąg:

Swift dokonał świadomego wyboru, aby nie zawierać wyjątki generowane przez arbitralnych nie ramek stosu, ponieważ było to technicznie niemożliwe, ale dlatego, że jego projektanci oceniać koszty są zbyt wysokie.

Problem polega na tym, że jeśli kod zostanie zamknięty wcześniej, ponieważ błędu, musi zostać zapisany, aby obsłużyć to wcześniejsze wyjście. W przeciwnym razie nie będzie w stanie zwolnić pamięci, nie zamknie pliku uchwytów/gniazd/połączeń z bazami danych/czymkolwiek, nie zwolni blokad, itd. W języku takim jak Java pisanie naprawdę wyjątkowego kodu wymaga niedorzecznej ilości bloków try/finally. To dlatego nikt tego nie robi. Wyjaśniają, które wyjątki są prawdopodobne i które zasoby są niebezpieczne do przecieku, a tylko chroni ich kod przed tymi konkretnymi przewidywanymi warunkami. Wtedy zdarza się coś nieprzewidzianego, a ich program się psuje.

Jest nawet gorzej w języku odniesienia liczone jak Swift, bo poprawnie zrównoważenie liczby odniesień w obecności wyjątkami wymaga w zasadzie każda funkcja obejmuje niejawna wreszcie blokować zrównoważyć wszystkie liczniki zachowują. Oznacza to, że kompilator musi wygenerować wiele dodatkowych kodów, poza tym, że niektóre wywołania lub inny zgłasza wyjątek. Ogromna większość tego kodu nigdy nie była, kiedykolwiek używana, ale musi tam być, wzdęcia procesu.

Z powodu tych problemów Swift zdecydował się nie obsługiwać tradycyjnych wyjątków od ; zamiast tego pozwala tylko na zgłaszanie błędów w specjalnie oznaczonych regionach kodu . Ale jako następstwo, oznacza to, że jeśli coś pójdzie nie tak w kodzie, który nie może się wyrzucić, to naprawdę może to zrobić, aby zapobiec katastrofie. A obecnie jedyną rzeczą, którą możesz zawiesić jest cały proces.

Aby uzyskać więcej informacji, zobacz

+1

Dzięki @MartinR ... Zauważyłem, że członkowie Swift wyładowali ciężar obsługi każdego małego lub dużego wyjątku i błędu dla programistów "od samego początku". –

+1

Dziękuję bardzo za dzielenie się, teraz przynajmniej uzasadnienie jest jasne, co wydawało się zagadkowym zaniedbaniem. – Crashalot

+2

Jest to w porządku ze mną, ale nadal potrzebuję przynajmniej być w stanie złapać sygnały, aby móc wdrożyć mój rejestr awarii. Nie wydaje się, żeby to działało; force unwrapping zero rzuca 'EXC_BAD_INSTRUCTION', którego nie mogę przechwycić ani z wyjątkiem, ani z procedur obsługi sygnału ... –

5

Jest to kod używam do logowania wszystkie wyjątki/błędy. Log.error(with:) to niestandardowa funkcja, w której przechowuję ślad stosu wraz z innymi informacjami. Thread.callStackSymbols to tablica łańcuchów i reprezentująca ślad stosu.

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

Wielkie dzięki, nawet nie wiedział o funkcji sygnału (...) –

+1

Należy pamiętać, że tylko" bezpieczny sygnał asynchroniczny " "funkcje mogą być bezpiecznie wywoływane z manipulatorów sygnałów. "printf" i powiązane funkcje nie są bezpieczne dla sygnałów asynchronicznych. –

+0

Gdzie używasz tego kodu? AppDelegate? Główny? Próbowałem dodać ten kod do mojej aplikacji bez powodzenia. –