Ao converter um projeto para usar o ARC, o que significa "mudar caso está no escopo protegido"?

283

Ao converter um projeto para usar o ARC, o que significa "mudar caso está no escopo protegido"? Estou convertendo um projeto para usar o ARC, usando o Xcode 4 Editar -> Refatorar -> Converter em ARC Objective-C ... Um dos erros que recebo é "a caixa de opção está no escopo protegido" em "algumas" das opções em um caso de interruptor.

Editar, aqui está o código:

o erro está marcado no caso "padrão":

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

Respostas:

651

Cercar cada caso em si com chaves {}. Isso deve resolver o problema (foi o que ocorreu em um de meus projetos).

FeifanZ
fonte
12
As chaves ajudam o compilador a entender o escopo. Eu sei que o GCC costumava emitir um aviso se você declarasse uma nova variável na primeira linha de uma instrução de caso sem chaves, e o vídeo da WWDC 2011 no ARC menciona algo sobre o fechamento de casos entre chaves. Se você quer saber o porquê, confira o vídeo - não me lembro de nada.
FeifanZ 27/09/11
87
Já faz um tempo, mas eu me lembro de algo no padrão C que não permitia a atribuição de variáveis ​​após uma instrução de caso, porque o código não está realmente dentro de um bloco. Adicionando chaves {...}depois casee antes da break, tudo dentro está em um bloco com escopo definido e se comportará conforme o esperado. Cheguei ao ponto de apenas bloquear automaticamente minhas casedeclarações para evitar esse tipo de problema.
Paul
2
Eu tive o mesmo problema. É uma mensagem de erro horrível e um bug foi arquivado (que será corrigido em uma versão futura do compilador) para corrigi-lo. Mas, sim, as regras de escopo nas instruções de caso em C são realmente muito ... estranhas.
Bb 27/09/11
59
Isso está ocorrendo porque você está declarando uma nova variável no escopo de um caso. O compilador não sabe como essa variável deve ter um escopo definido (ela pertence a todos os casos de switches ou apenas ao caso atual?) Agrupar a implementação do caso entre parênteses cria um escopo para a variável viver dentro, para que o compilador possa gerenciar adequadamente é vida.
Shinohara
1
Observe que isso também pode acontecer ao declarar uma variável dentro de um bloco dentro de uma instrução de caso sem chaves. Isso foi um arranhão na cabeça por um minuto ou dois. =)
slycrel
14

Difícil ter certeza sem olhar para o código, mas provavelmente significa que há alguma declaração de variável acontecendo dentro do comutador e o compilador não pode dizer se há um caminho claro para o ponto de desalocação necessário.

Flyingdiver
fonte
9

Existem 2 maneiras fáceis de resolver esse problema:

  • Você provavelmente está declarando variáveis. Mova a declaração das variáveis ​​para fora da instrução switch
  • Coloque o bloco inteiro entre colchetes {}

O compilador não pode calcular a linha de código quando as variáveis ​​devem ser liberadas. Causando este erro.

Vincent
fonte
5

Para mim, o problema começou no meio de um comutador e os colchetes não funcionaram, a menos que você precise incluir {} IN ALL declarações de casos anteriores. Para mim, o erro ocorreu quando recebi a declaração

NSDate *start = [NSDate date];

no caso anterior. Depois de excluir isso, todas as instruções de caso subseqüentes foram limpas da mensagem de erro do escopo protegido

Z. Zepos
fonte
Mesma coisa; caso erro no meio. Eu só tive que mover a declaração da variável acima do comutador (não dependia de maiúsculas e minúsculas). Não precisei adicionar chaves nos casos (desta vez).
eGanges
3

Antes:

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

Mudei a definição do NSDate antes do switch e ele corrigiu o problema de compilação:

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

}
Roozbeh Zabihollahi
fonte
2

Declare as variáveis ​​fora do switch e instancie-as dentro do caso. Isso funcionou perfeitamente para mim usando o Xcode 6.2

user3433008
fonte
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: Verifique! A sintaxe da linha em negrito e itálico. Retifique-o e você está pronto para ir.

hemant_maverik
fonte
0

Coloque entre chaves {}o código entre a instrução case e a quebra em cada caso. Funcionou no meu código.

David Vargas
fonte