При преобразовании проекта для использования ARC, что означает «случай переключения находится в защищенной области»?


283

При преобразовании проекта для использования ARC, что означает «случай переключения находится в защищенной области»? Я преобразовываю проект для использования ARC, используя Xcode 4 Edit -> Refactor -> Convert to Objective-C ARC ... Одна из ошибок, которые я получаю, это «случай переключения находится в защищенной области» на «некоторых» из переключателей в случай переключения.

Редактировать, вот код:

ОШИБКА отмечена в случае «по умолчанию»:

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

Ответы:


651

Окружите каждый случай самими скобками {}. Это должно решить проблему (это было сделано для меня в одном из моих проектов).


12
Скобки помогают компилятору понять область действия. Я знаю, что GCC выдает предупреждение, если вы объявляете новую переменную в первой строке оператора case без фигурных скобок, а в видео WWDC 2011 об ARC упоминается что-то о заключении в фигурные скобки. Если ты хочешь знать почему, посмотри это видео - я не могу вспомнить, что у меня в голове.
FeifanZ

87
Это было давно, но мне кажется, что я кое-что вспомнил в стандарте C, что не позволяло присваивать переменные после оператора case, потому что код на самом деле не находится внутри блока. Добавляя фигурные скобки {...}после caseи перед break, все внутри находится в блоке с областью видимости и будет вести себя как ожидалось. Я дошел до того, что просто автоматически блокирую свои caseвысказывания, чтобы избежать подобных проблем.
Пол

2
Я столкнулся с той же проблемой. Это ужасное сообщение об ошибке, и была подана ошибка (которая будет исправлена ​​в будущей версии компилятора) для ее исправления. Но да, правила области видимости в операторах case в C действительно очень ... странные.
Бум

59
Это происходит потому, что вы объявляете новую переменную в рамках дела. Компилятор не знает, как должна быть ограничена эта переменная (относится ли она ко всем случаям переключателей или только к текущему случаю?), Заключая реализацию кейса в скобки, создает область действия переменной, чтобы компилятор мог правильно управлять это жизнь.
Шинохара

1
Обратите внимание, что это также может произойти при объявлении переменной в блоке внутри оператора case без фигурных скобок. Это была головная боль на минуту или две. =)
slycrel

14

Трудно быть уверенным, не глядя на код, но это, вероятно, означает, что внутри коммутатора происходит некоторое объявление переменной, и компилятор не может определить, существует ли четкий путь к требуемой точке освобождения.


9

Есть 2 простых способа решить эту проблему:

  • Вы, вероятно, объявляете переменные. Переместите объявление переменных за пределы оператора switch
  • Поместите весь блок case между фигурными скобками {}

Компилятор не может вычислить строку кода, когда переменные должны быть освобождены. Вызывает эту ошибку.


5

Для меня проблема началась с середины коммутатора, и фигурные скобки не сработали, если только вы не включили {} IN ALL предыдущие операторы case. Для меня ошибка пришла, когда у меня было утверждение

NSDate *start = [NSDate date];

в предыдущем случае. После того как я удалил это, все последующие инструкции case были очищены от сообщения об ошибке защищенной области


То же самое; ошибка в середине. Мне нужно было только переместить объявление переменной над переключателем (оно не зависело от регистра). Мне не нужно было добавлять скобки вокруг чехлов (на этот раз).
eGanges

3

Перед:

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

Я передвинул определение NSDate до switch, и это исправило проблему компиляции:

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

}

2

Объявите переменные вне коммутатора, а затем создайте их экземпляр в кейсе. Это отлично работает для меня, используя 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;
    }

Примечание: проверьте! Синтаксис жирной и курсивной линии. Исправьте это, и вы готовы идти.


0

Окружите скобками {}код между оператором case и разрывом в каждом случае. Это сработало в моем коде.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.