Lors de la conversion d'un projet pour utiliser ARC, que signifie «le commutateur est dans la portée protégée»?

283

Lors de la conversion d'un projet pour utiliser ARC, que signifie "le commutateur est dans la portée protégée"? Je convertis un projet pour utiliser ARC, en utilisant Xcode 4 Edit -> Refactor -> Convert to Objective-C ARC ... L'une des erreurs que j'obtiens est "le boîtier du commutateur est dans la portée protégée" sur "certains" des commutateurs dans un boîtier de commutation.

Edit, voici le code:

L'ERREUR est marquée sur le cas "par défaut":

- (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
la source

Réponses:

651

Entourez chaque boîtier lui-même avec des accolades {}. Cela devrait résoudre le problème (il l'a fait pour moi dans l'un de mes projets).

FeifanZ
la source
12
Les accolades aident le compilateur à comprendre la portée. Je sais que GCC émettait un avertissement si vous déclariez une nouvelle variable à la première ligne d'une déclaration de casse sans les accolades, et la vidéo de la WWDC 2011 sur ARC mentionne quelque chose à propos de la mise en boîtier des accolades. Si vous voulez savoir pourquoi, regardez cette vidéo — je ne me souviens pas du haut de ma tête.
FeifanZ
87
Cela fait un moment, mais je semble me souvenir de quelque chose dans la norme C qui n'autorisait pas l'affectation de variables après une instruction case car le code n'est pas vraiment à l'intérieur d'un bloc. En ajoutant des accolades {...}après caseet avant le break, tout à l'intérieur est dans un bloc de portée et se comportera comme prévu. J'en suis arrivé au point que je fais juste automatiquement un bloc de mes casedéclarations pour éviter ce genre de problème.
Paul
2
J'ai rencontré le même problème. C'est un horrible message d'erreur et un bug a été déposé (qui sera corrigé dans une future version du compilateur) pour le corriger. Mais, oui, les règles de cadrage dans les déclarations de cas en C sont vraiment très ... étranges.
bbum
59
Cela se produit car vous déclarez une nouvelle variable dans le cadre d'un cas. Le compilateur ne sait pas comment cette variable doit être étendue (appartient-elle à tous les cas de commutateurs ou seulement au cas actuel?). c'est la vie.
Shinohara
1
Notez que cela peut également se produire lors de la déclaration d'une variable dans un bloc dans une instruction case sans accolades. Ce fut un gratte-tête pendant une minute ou deux. =)
slycrel
14

Difficile d'être sûr sans regarder le code, mais cela signifie probablement qu'il y a une déclaration de variable en cours à l'intérieur du commutateur et le compilateur ne peut pas dire s'il y a un chemin clair vers le point de désallocation requis.

Flyingdiver
la source
9

Il existe 2 façons simples de résoudre ce problème:

  • Vous déclarez probablement des variables. Déplacer la déclaration des variables en dehors de l'instruction switch
  • Mettez le bloc de cas entier entre crochets {}

Le compilateur ne peut pas calculer la ligne de code lorsque les variables doivent être publiées. Causer cette erreur.

Vincent
la source
5

Pour moi, le problème a commencé au milieu d'un commutateur et les accolades n'ont pas fonctionné, sauf si vous devez inclure {} DANS TOUTES les déclarations de cas précédentes. Pour moi, l'erreur est venue quand j'ai eu la déclaration

NSDate *start = [NSDate date];

dans le cas précédent. Après avoir supprimé cela, toutes les instructions de cas suivantes sont venues du message d'erreur de portée protégée

Z. Zepos
la source
Même chose; erreur de cas au milieu. Je n'ai eu qu'à déplacer la déclaration de variable au-dessus du commutateur (cela ne dépendait pas de la casse). Je n'ai pas eu à ajouter d'accolades autour des boîtiers (cette fois).
eGanges
3

Avant:

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

J'ai déplacé la définition NSDate avant de basculer, et cela a résolu le problème de compilation:

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

}
Roozbeh Zabihollahi
la source
2

Déclarez les variables à l'extérieur du commutateur, puis instanciez-les à l'intérieur du cas. Cela a parfaitement fonctionné pour moi en utilisant Xcode 6.2

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

Remarque: Vérifiez! La syntaxe de la ligne en gras et en italique. Rectifiez-le et vous êtes prêt à partir.

hemant_maverik
la source
0

Entourez d'accolades {}le code entre l' instruction case et la coupure dans chaque cas. Cela a fonctionné sur mon code.

David Vargas
la source