Co oznacza „konwersja skrzynki w chronionym zakresie” przy konwersji projektu na ARC?

283

Co oznacza „konwersja skrzynki w chronionym zakresie” przy konwersji projektu na ARC? Konwertuję projekt do użycia ARC, używając Xcode 4 Edycja -> Refaktoryzacja -> Konwertuj na ARC Objective-C ... Jednym z błędów, które dostaję, jest to, że „skrzynka przełączników jest chroniona” na „niektórych” przełącznikach w skrzynka przełączników.

Edytuj, oto kod:

BŁĄD jest zaznaczony na „domyślnym” przypadku:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"";
    UITableViewCell *cell ;
    switch (tableView.tag) {
        case 1:
            CellIdentifier = @"CellAuthor";
            cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (cell == nil) {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
        cell.textLabel.text = [[prefQueries objectAtIndex:[indexPath row]] valueForKey:@"queryString"];
        break;
    case 2:
        CellIdentifier = @"CellJournal";
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
        cell.textLabel.text = [[prefJournals objectAtIndex:[indexPath row]] valueForKey:@"name"];

        NSData * icon = [[prefJournals objectAtIndex:[indexPath row]] valueForKey:@"icon"];
        if (!icon) {
            icon = UIImagePNGRepresentation([UIImage imageNamed:@"blank72"]);
        }
        cell.imageView.image = [UIImage imageWithData:icon];

        break;

    default:
        CellIdentifier = @"Cell";
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            }
        break;
    }


    return cell;
}
Ali
źródło

Odpowiedzi:

651

Otocz każdą obudowę szelkami {}. To powinno naprawić problem (zrobiło to dla mnie w jednym z moich projektów).

FeifanZ
źródło
12
Nawiasy klamrowe pomagają kompilatorowi zrozumieć zakres. Wiem, że GCC zwykło wydawać ostrzeżenie, jeśli zadeklarowałeś nową zmienną w pierwszym wierszu instrukcji case bez nawiasów klamrowych, a wideo WWDC 2011 na temat ARC wspomina coś o zamykaniu skrzynek w nawiasach klamrowych. Jeśli chcesz wiedzieć, dlaczego, sprawdź to wideo - nie pamiętam z głowy.
FeifanZ
87
Minęło trochę czasu, ale wydaje mi się, że pamiętam coś w standardzie C, które nie pozwalało na przypisywanie zmiennych po instrukcji case, ponieważ kod nie jest tak naprawdę wewnątrz bloku. Dodając nawiasy klamrowe {...}po casei przed break, wszystko w środku jest w bloku z zakresem i będzie działało zgodnie z oczekiwaniami. Doszedłem do tego, że po prostu automatycznie blokuję moje casewypowiedzi, aby uniknąć tego rodzaju problemów.
Paul
2
Natrafiłem na ten sam problem. Jest to okropny komunikat o błędzie i zgłoszony został błąd (który zostanie naprawiony w przyszłej wersji kompilatora), aby go naprawić. Ale tak, zasady określania zakresu w instrukcjach przypadków w C są naprawdę bardzo ... dziwne.
bbum
59
Dzieje się tak, ponieważ deklarujesz nową zmienną w ramach sprawy. Kompilator nie wie, w jaki sposób ta zmienna powinna mieć zasięg (czy należy ona do wszystkich przypadków przełączników, czy tylko bieżącej sprawy?). Zawijanie implementacji sprawy w nawiasach tworzy zakres, w którym zmienna może się w niej znajdować, aby kompilator mógł odpowiednio zarządzać to całe życie.
Shinohara,
1
Zauważ, że może się to zdarzyć również podczas deklarowania zmiennej w bloku w instrukcji case bez nawiasów klamrowych. To był drapak głowy przez minutę lub dwie. =)
slycrel
14

Trudno być pewnym, nie patrząc na kod, ale prawdopodobnie oznacza to, że wewnątrz przełącznika dzieje się deklaracja zmiennej, a kompilator nie jest w stanie stwierdzić, czy istnieje jasna ścieżka do wymaganego punktu dealloc.

Flyingdiver
źródło
9

Istnieją 2 proste sposoby rozwiązania tego problemu:

  • Prawdopodobnie deklarujesz zmienne. Przenieś deklarację zmiennych poza instrukcję switch
  • Umieść cały blok skrzynki między nawiasami klamrowymi {}

Kompilator nie może obliczyć wiersza kodu, kiedy zmienne mają zostać zwolnione. Powodowanie tego błędu.

Vincent
źródło
5

Dla mnie problem zaczął się na środku przełącznika i nawiasy klamrowe nie zadziałały, chyba że musisz dołączyć {} WSZYSTKIMI poprzednim instrukcjom. Dla mnie błąd przyszedł, gdy miałem oświadczenie

NSDate *start = [NSDate date];

w poprzednim przypadku. Po usunięciu tego, wszystkie kolejne instrukcje sprawy zostały usunięte z komunikatu o błędzie chronionego zakresu

Z. Zepos
źródło
Ta sama rzecz; błąd sprawy w środku. Musiałem tylko przesunąć deklarację zmiennej nad przełącznik (nie zależało to od wielkości liter). Nie musiałem dodawać aparatów ortodontycznych wokół skrzynek (tym razem).
eGanges
3

Przed:

    case 2:
        NSDate *from = [NSDate dateWithTimeIntervalSince1970:1388552400];
        [self refreshContents:from toDate:[NSDate date]];
        break;

Przesunąłem definicję NSDate przed przełączeniem i naprawiłem problem z kompilacją:

NSDate *from;  /* <----------- */
switch (index) {
    ....
    case 2:
        from = [NSDate dateWithTimeIntervalSince1970:1388552400];
        [self refreshContents:from toDate:[NSDate date]];
        break;

}
Roozbeh Zabihollahi
źródło
2

Zadeklaruj zmienne poza przełącznikiem, a następnie ułóż je w skrzynce. To działało idealnie dla mnie przy użyciu Xcode 6.2

użytkownik3433008
źródło
1
default:
        CellIdentifier = @"Cell";
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            ***initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];***
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            }
        break;
    }

Uwaga: Sprawdź! Składnia linii pogrubionej i pochylonej. Wyprostuj i gotowe.

hemant_maverik
źródło
0

Otocz nawiasami klamrowymi {}kod między instrukcją case i przerwą w każdym przypadku. Działa z moim kodem.

David Vargas
źródło