2009-07-31 9 views
9

Chcę, aby moja aplikacja nigdy się nie głupiła. Wiem, że jakość kodu jest głównym rozwiązaniem tego problemu. Ale nadal potrzebuję aplikacji, aby nigdy się nie zawieść, gdy pojawi się jakiś nieoczekiwany błąd. Oto kod, który chcę wypróbować.Rozwój iPhone'a: ​​Jak złapać wyjątek/NSError w Objective-C?

-(void)testException 
{ 
    @try 
    { 
     NSString* str; 
     [str release]; 
    } 
    @catch(NSException* ex) 
    { 
     NSLog(@"Bug captured"); 
    } 
} 

Wiem, że ten nie działa. Ponieważ release nigdy nie przenosi wyjątku. Oto moje pytania:

  1. Jak osiągnąć ten cel, błąd zostanie przechwycony, bez awarii?
  2. Skąd wiadomo, która biblioteka systemowa zgłosi wyjątek i mogę napisać kod i wiem, że działa?

Oto co czytałem

  • a. Tematy programowania wyjątków dla: Cocoa
  • b. Obsługa błędów programowania
    Guide kakao

pochodzę doświadczonego programistę tle Microsoft, w której wyjątek haczyk lub nieoczekiwany wyjątek zawsze mój program zapobiegania awariom w bardzo złych warunkach.

W jaki sposób faceci/dziewczęta (programiści Mac genius) robili awaryjne programy? Podziel się wrażeniami.

Odpowiedz

3

Jedną z rzeczy, którą masz, jest to, że str nigdy nie jest inicjowany, co oznacza, że ​​str może wskazywać na zero (ale nie jest to gwarantowane). Zdecydowanie wskazuje na śmieci.

Jeśli przejdziesz przez swój kod, mogę prawie zagwarantować, że twoje wydanie zostanie wywołane na zero, co w Objective-C jest całkowicie poprawne.

Spróbuj zrobić tak:

NSString *str = [[NSString alloc] initWithString:@"a string"]; 
[str release]; 
[str release]; 

Wywołanie uwalnianie nie zwalnianie obiektu, to po prostu dekrementuje zachować rachubę przez 1. Jeżeli obiekty zachowują liczba jest 0,

[self dealloc]; 

nazywa się automatycznie .

Jeśli powyższy kod nie rzuca wyjątku natychmiast, może to być spowodowane faktem, że faktyczny komunikat o wycofaniu jest opóźniony w jakimś przyszłym punkcie (nie jestem pewien dokładnie, kiedy wywoływana jest komenda dealloc po tym, jak licznik zatrzymań osiągnie 0. I nazywa się natychmiast i na tej samej nitce, ale niektórzy ninja z kakao będą wiedzieć na pewno).

Co można zrobić, to dodać kategorię do NSObject i zaimplementować metody dealloc i release i spróbować złapać tam wyjątek.

- (void)dealloc{ 

@try 
    { 
     [super dealloc]; 
    } 
@catch(NSException* ex) 
    { 
     NSLog(@"Bug captured"); 
    } 

} 



- (void)release{ 

    @try 
     { 
      [super release]; 
     } 
    @catch(NSException* ex) 
     { 
      NSLog(@"Bug captured"); 
     } 

    } 

Dodatkowym atutem jest to, że kod będzie ważny dla każdego obiektu w aplikacji, ponieważ jest to kategoria na NSObject.

Aby być kompletnym, jeśli po prostu przećwiczysz zasady zarządzania pamięcią, wszystko będzie dobrze.

+0

Dzięki za odpowiedź. Twoja odpowiedź pomoże mi lepiej zrozumieć zarządzanie pamięcią i poszerzyć moją wiedzę na temat Celu C. Jednak próbowałem kodu, nigdy się nie zawieszają (powinny być, wydaje 4 razy, liczba odwołań powinna wynosić -3, jeśli to możliwe). ale w ogóle nie zdarzyła się awaria, nie ma też wyjątku. Wiem, że kiedyś się rozbije. ale nie wiem kiedy. wracając do podstawowego, czy istnieje sposób na uniknięcie awarii? –

+0

Nie przejmuj się zatrzymaniem zliczeń. Nigdy nie powinieneś tego sprawdzać, nigdy nie jest tak, jak ci się wydaje, z różnych powodów. Musisz zająć się zarządzaniem pamięcią jedną metodą na raz. Szukaj Stackoverflow i google dla zarządzania pamięcią kakao. Jest mnóstwo zasobów, które mogą ci pomóc. Na początku może być trudny do nauczenia, ale staje się bardziej automatyczny. –

12

Objective-C jest niezarządzanym środowiskiem wykonawczym; kod kompilowany jest uruchamiany bezpośrednio na procesorze, a nie na maszynie wirtualnej. Oznacza to, że nie masz warstwy nadzorczej, która może przechwycić każdy możliwy tryb awarii w taki sam sposób, jak podczas pracy w maszynie wirtualnej .NET lub maszynie wirtualnej JVM. Krótko mówiąc, jedynym sposobem, w jaki będziesz całkowicie pewien, że program nie może się zawiesić, jest bardzo dokładne kodowanie i bardzo dokładne testowanie. I nawet wtedy nie jesteś pewien, po prostu uważasz, że jesteś.

Najnowsza wersja Xcode integruje analizator statyczny Clang ("Build and Analyse" w menu Build), który może identyfikować niektóre klasy potencjalnych błędów - jestem prawie pewien, że oznaczałoby to twój przykład powyżej, na przykład) . Ale tutaj nie ma magicznej kuli; jedynym rozwiązaniem jest ciężka praca.

4

Test Test Test Test Test

Można spędzić cały dzień pisania wyjątku obsługi kodu ewentualnych wyjątków (które w praktyce nigdy nie nastąpi), można też tworzyć dokładne zestawy testów i pisać tylko teleskopowe wyjątek sytuacje, które występują w praktyce.

Dlatego prawie nigdy nie piszę obsługi wyjątków. Jeśli usuniesz podstawowe problemy, które powodują wyjątek, nie musisz nic robić.

Oczywiście są sytuacje, w których nie można zagwarantować, że wywołanie metody nie spowoduje wyjątku i trzeba się przygotować, ale zawijanie wszystkiego w blokach @ try/@ catch zdecydowanie nie jest rozwiązaniem.