Al convertir un proyecto para usar ARC, ¿qué significa "cambiar el caso está en el alcance protegido"?

283

Al convertir un proyecto para usar ARC, ¿qué significa "cambiar el caso está en el alcance protegido"? Estoy convirtiendo un proyecto para usar ARC, usando Xcode 4 Edit -> Refactor -> Convert to Objective-C ARC ... Uno de los errores que obtengo es "la caja del interruptor está en el alcance protegido" en "algunos" de los interruptores en Una caja de interruptor.

Editar, aquí está el código:

el ERROR está marcado en el caso "predeterminado":

- (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
fuente

Respuestas:

651

Rodea cada caso con llaves {}. Eso debería solucionar el problema (lo hizo para mí en uno de mis proyectos).

FeifanZ
fuente
12
Las llaves ayudan al compilador a comprender el alcance. Sé que GCC solía emitir una advertencia si declaraba una nueva variable en la primera línea de una declaración de caso sin las llaves, y el video de WWDC 2011 en ARC menciona algo acerca de encerrar casos en llaves. Si quieres saber por qué, mira ese video, no puedo recordarlo.
FeifanZ
87
Ha pasado un tiempo, pero parece recordar algo en el estándar C que no permitía la asignación de variables después de una declaración de caso porque el código no está realmente dentro de un bloque. Al agregar llaves {...}después del casey antes del break, todo dentro está en un bloque de alcance y se comportará como se esperaba. He llegado al punto de que automáticamente hago un bloqueo de mis casedeclaraciones para evitar este tipo de problema.
Paul
2
Me encontré con el mismo problema. Es un mensaje de error horrible y se ha archivado un error (que se solucionará en una versión futura del compilador) para corregirlo. Pero sí, las reglas de alcance dentro de las declaraciones de caso en C son realmente muy ... extrañas.
bbum
59
Esto ocurre porque está declarando una nueva variable dentro del alcance de un caso. El compilador no sabe cómo se debe definir el alcance de esta variable (¿pertenece a todos los casos de conmutadores o solo al caso actual?) Al envolver la implementación del caso entre paréntesis, se crea un ámbito para que la variable viva para que el compilador pueda administrar adecuadamente Es de por vida.
Shinohara
1
Tenga en cuenta que esto también puede ocurrir al declarar una variable dentro de un bloque dentro de una declaración de caso sin llaves. Eso fue un rascador de cabeza por un minuto o dos. =)
slycrel
14

Es difícil estar seguro sin mirar el código, pero probablemente significa que hay una declaración de variables dentro del conmutador y el compilador no puede saber si hay una ruta clara hacia el punto de reparto requerido.

Flyingdiver
fuente
9

Hay 2 formas fáciles de resolver este problema:

  • Probablemente estés declarando variables. Mueva la declaración de las variables fuera de la instrucción switch
  • Coloque todo el bloque de mayúsculas y minúsculas entre llaves {}

El compilador no puede calcular la línea de código cuando se van a liberar las variables. Causando este error.

Vincent
fuente
5

Para mí, el problema comenzó en medio de un interruptor y las llaves no funcionaron, a menos que tenga que incluir {} EN TODAS las declaraciones de casos anteriores. Para mí, el error vino cuando tuve la declaración

NSDate *start = [NSDate date];

en el caso anterior Después de eliminar esto, toda la declaración de caso posterior se borró del mensaje de error de alcance protegido

Z. Zepos
fuente
La misma cosa; error de caso en el medio. Solo tuve que mover la declaración de variable sobre el interruptor (no dependía de mayúsculas y minúsculas). No tuve que agregar llaves alrededor de los casos (esta vez).
eGanges
3

Antes de:

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

Moví la definición de NSDate antes del cambio, y solucionó el problema de compilación:

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

}
Roozbeh Zabihollahi
fuente
2

Declare las variables fuera del conmutador, luego ejecútelas dentro del caso. Eso funcionó perfectamente para mí usando Xcode 6.2

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

Nota: ¡Verificar! La sintaxis de la línea en negrita y cursiva. Rectifícalo y listo.

hemant_maverik
fuente
0

Rodea con llaves {}el código entre la declaración del caso y el corte en cada caso. Funcionó en mi código.

David Vargas
fuente