Quando si converte un progetto in ARC, cosa significa "switch case è in ambito protetto"?


283

Quando si converte un progetto in ARC, cosa significa "switch case is in scope scope"? Sto convertendo un progetto per usare ARC, usando Xcode 4 Modifica -> Refactor -> Converti in Objective-C ARC ... Uno degli errori che ottengo è "la custodia dello switch è in ambito protetto" su "alcuni" degli switch in una custodia.

Modifica, ecco il codice:

l'ERRORE è contrassegnato sul caso "predefinito":

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

Risposte:


651

Circonda ogni caso stesso con parentesi graffe {}. Ciò dovrebbe risolvere il problema (lo ha fatto per me in uno dei miei progetti).


12
Le parentesi graffe aiutano il compilatore a comprendere l'ambito. So che GCC emetteva un avvertimento se si dichiarava una nuova variabile nella prima riga di un'istruzione case senza parentesi graffe e il video WWDC 2011 su ARC menziona qualcosa sull'inclusione di casi tra parentesi graffe. Se vuoi sapere perché, dai un'occhiata a quel video: non riesco a ricordare la parte superiore della mia testa.
FeifanZ,

87
È passato un po 'di tempo, ma mi sembra di ricordare qualcosa nello standard C che non ha consentito l'assegnazione di variabili dopo un'istruzione case perché il codice non è realmente all'interno di un blocco. Aggiungendo parentesi graffe {...}dopo casee prima di break, tutto all'interno è in un blocco con ambito e si comporterà come previsto. Sono arrivato al punto di fare automaticamente un blocco delle mie casedichiarazioni per evitare questo tipo di problema.
Paolo,

2
Ho riscontrato lo stesso problema. È un orribile messaggio di errore ed è stato archiviato un bug (che verrà corretto in una versione futura del compilatore) per correggerlo. Ma sì, le regole di scoping all'interno delle istruzioni case in C sono davvero molto ... strane.
bbum,

59
Ciò si verifica perché stai dichiarando una nuova variabile nell'ambito di un caso. Il compilatore non sa come questa variabile debba essere definita (appartiene a tutti i casi di switch o solo al caso corrente?) Che avvolge l'implementazione del caso tra parentesi crea un ambito in cui la variabile deve vivere in modo che il compilatore possa gestire correttamente è la vita.
Shinohara,

1
Si noti che ciò può accadere anche quando si dichiara una variabile all'interno di un blocco all'interno di un'istruzione case senza parentesi graffe. È stato un grattacapo per un minuto o due. =)
slycrel l'

14

Difficile essere sicuri senza guardare il codice, ma probabilmente significa che c'è qualche dichiarazione variabile all'interno dello switch e il compilatore non può dire se c'è un percorso chiaro per il punto dealloc richiesto.


9

Esistono 2 semplici modi per risolvere questo problema:

  • Probabilmente stai dichiarando variabili. Sposta la dichiarazione delle variabili all'esterno dell'istruzione switch
  • Metti l'intero case case tra parentesi graffe {}

Il compilatore non può calcolare la riga di codice quando devono essere rilasciate le variabili. Causando questo errore.


5

Per me, il problema è iniziato nel mezzo di un interruttore e le parentesi graffe non sono state risolte, a meno che non sia necessario includere {} IN TUTTE le precedenti dichiarazioni del caso. Per me l'errore è arrivato quando ho avuto la dichiarazione

NSDate *start = [NSDate date];

nel caso precedente. Dopo averlo eliminato, tutte le successive dichiarazioni del caso sono risultate pulite dal messaggio di errore dell'ambito protetto


Stessa cosa; errore case nel mezzo. Ho dovuto solo spostare la dichiarazione della variabile sopra l'interruttore (non dipendeva maiuscole e minuscole). Non ho dovuto aggiungere parentesi graffe attorno ai casi (questa volta).
eGanges,

3

Prima:

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

Ho spostato la definizione di NSDate prima di passare e risolto il problema di compilazione:

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

}

2

Dichiarare le variabili all'esterno dell'interruttore, quindi istanziarle all'interno del caso. Per me ha funzionato perfettamente con Xcode 6.2


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: controllare! La sintassi della linea in grassetto e in corsivo. Correggilo e sei a posto.


0

Circonda con parentesi graffe {}il codice tra l' istruzione case e l' interruzione in ogni caso. Ha funzionato sul mio codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.