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.