Was bedeutet bei der Konvertierung eines Projekts zur Verwendung von ARC "Switch Case befindet sich im geschützten Bereich"?


283

Was bedeutet bei der Konvertierung eines Projekts zur Verwendung von ARC "Switch Case ist im geschützten Bereich"? Ich konvertiere ein Projekt zur Verwendung von ARC mit Xcode 4 Bearbeiten -> Refactor -> In Objective-C ARC konvertieren ... Einer der Fehler, den ich erhalte, ist "Schaltergehäuse befindet sich im geschützten Bereich" für "einige" der Schalter in ein Schaltergehäuse.

Bearbeiten, hier ist der Code:

Der FEHLER ist im "Standard" -Fall markiert:

- (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;
}

Antworten:


651

Umgeben Sie jeden Fall selbst mit Klammern {}. Das sollte das Problem beheben (es hat für mich in einem meiner Projekte getan).


12
Die geschweiften Klammern helfen dem Compiler, den Umfang zu verstehen. Ich weiß, dass GCC eine Warnung ausgegeben hat, wenn Sie in der ersten Zeile einer case-Anweisung eine neue Variable ohne geschweifte Klammern deklariert haben, und das WWDC 2011-Video zu ARC erwähnt etwas über das Einschließen von Fällen in geschweifte Klammern. Wenn Sie wissen möchten, warum, schauen Sie sich dieses Video an - ich kann mich nicht mehr genau erinnern.
FeifanZ

87
Es ist eine Weile her, aber ich erinnere mich an etwas im C-Standard, das nach einer case-Anweisung keine Variablenzuweisung zuließ, da sich der Code nicht wirklich in einem Block befindet. Durch Hinzufügen von geschweiften Klammern {...}nach caseund vor dem breakbefindet sich alles in einem Block mit Gültigkeitsbereich und verhält sich wie erwartet. Ich bin zu dem Punkt gekommen, dass ich meine caseAussagen einfach automatisch blockiere, um diese Art von Problem zu vermeiden.
Paul

2
Ich bin auf das gleiche Problem gestoßen. Es ist eine schreckliche Fehlermeldung und es wurde ein Fehler gemeldet (der in einer zukünftigen Version des Compilers behoben wird), um ihn zu korrigieren. Aber ja, die Scoping-Regeln in case-Anweisungen in C sind wirklich sehr ... seltsam.
bbum

59
Dies liegt daran, dass Sie eine neue Variable im Rahmen eines Falls deklarieren. Der Compiler weiß nicht, wie diese Variable definiert werden soll (gehört sie zu allen Switch-Fällen oder nur zum aktuellen Fall?). Wenn die Implementierung des Falls in Klammern eingeschlossen wird, kann die Variable in diesem Bereich leben, damit der Compiler sie ordnungsgemäß verwalten kann Es ist lebenslang.
Shinohara

1
Beachten Sie, dass dies auch passieren kann, wenn eine Variable innerhalb eines Blocks innerhalb einer case-Anweisung ohne geschweifte Klammern deklariert wird. Das war ein oder zwei Minuten lang ein Kopfkratzer. =)
Slycrel

14

Es ist schwer sicher zu sein, ohne den Code zu betrachten, aber es bedeutet wahrscheinlich, dass im Switch eine Variablendeklaration stattfindet und der Compiler nicht erkennen kann, ob es einen klaren Pfad zum erforderlichen Dealloc-Punkt gibt.


9

Es gibt zwei einfache Möglichkeiten, um dieses Problem zu lösen:

  • Sie deklarieren wahrscheinlich Variablen. Verschieben Sie die Deklaration der Variablen außerhalb der switch-Anweisung
  • Setzen Sie den gesamten Fallblock zwischen geschweifte Klammern {}

Der Compiler kann die Codezeile nicht berechnen, wenn die Variablen freigegeben werden sollen. Diesen Fehler verursachen.


5

Für mich begann das Problem in der Mitte eines Schalters und geschweifte Klammern funktionierten nicht, es sei denn, Sie müssen {} IN ALLE vorherigen case-Anweisungen einfügen. Für mich kam der Fehler, als ich die Aussage hatte

NSDate *start = [NSDate date];

im vorherigen Fall. Nachdem ich dies gelöscht hatte, wurden alle nachfolgenden case-Anweisungen von der Fehlermeldung für den geschützten Bereich befreit


Gleiche Sache; Fallfehler in der Mitte. Ich musste nur die Variablendeklaration über den Schalter verschieben (es war nicht fallabhängig). Ich musste (diesmal) keine Klammern um die Fälle anbringen.
eGanges

3

Vor:

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

Ich habe die NSDate-Definition vor dem Wechsel verschoben und das Kompilierungsproblem behoben:

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

}

2

Deklarieren Sie die Variablen außerhalb des Schalters und instanziieren Sie sie dann innerhalb des Gehäuses. Das hat bei mir mit Xcode 6.2 perfekt funktioniert


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

Hinweis: Überprüfen! Die Syntax der fett und kursiv geschriebenen Zeile. Korrigieren Sie es und Sie können loslegen.


0

Umschließen Sie {}den Code zwischen der case- Anweisung und der Unterbrechung jeweils mit geschweiften Klammern . Es hat bei meinem Code funktioniert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.