При преобразовании проекта для использования ARC что означает переключатель case is in protected scope?

При преобразовании проекта для использования 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;
}

person Ali    schedule 26.09.2011    source источник


Ответы (8)


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

person FeifanZ    schedule 26.09.2011
comment
Фигурные скобки помогают компилятору понять область видимости. Я знаю, что GCC выдавал предупреждение, если вы объявляли новую переменную в первой строке оператора case без фигурных скобок, а в видео WWDC 2011 на ARC упоминается что-то о заключении регистров в фигурные скобки. Если вы хотите знать, почему, посмотрите это видео - я не могу припомнить это с головы до ног. - person FeifanZ; 27.09.2011
comment
Прошло некоторое время, но я, кажется, помню что-то в стандарте C, которое не позволяло присваивать переменные после оператора case, потому что код на самом деле не находится внутри блока. При добавлении фигурных скобок {...} после case и перед break все внутри находится в блоке с ограниченным объемом и будет вести себя так, как ожидалось. Я дошел до того, что просто автоматически делаю блок из своих операторов case, чтобы избежать подобных проблем. - person Paul; 27.09.2011
comment
Я столкнулся с той же проблемой. Это ужасное сообщение об ошибке, и была внесена ошибка (которая будет исправлена ​​в будущей версии компилятора) для ее исправления. Но да, правила области видимости в операторах case в C действительно очень ... странные. - person bbum; 27.09.2011
comment
Это происходит потому, что вы объявляете новую переменную в рамках дела. Компилятор не знает, как эта переменная должна иметь область видимости (относится ли она ко всем случаям переключателей или только к текущему случаю?). Заключение реализации случая в скобки создает область, в которой переменная будет жить, чтобы компилятор мог правильно управлять это жизнь. - person Shinohara; 06.07.2012
comment
Обратите внимание, что это также может произойти при объявлении переменной в блоке внутри оператора case без фигурных скобок. Минуту или две это было головной болью. знак равно - person slycrel; 11.06.2014
comment
+1 к slycrel ... Я подумал, что я полностью понял, что означает эта ошибка, но я смотрю на строку несколько минут и говорю: Но я НЕ объявляю переменную, черт возьми! Ах, но я объявляю переменную в блоке, который передаю в качестве параметра ... и это считается неявным объявлением переменной. Хороший. - person user435779; 30.10.2014
comment
То же самое, но обратите внимание, что объявление переменной в блоке case, что сбивает с толку, приведет к появлению ошибки в начале блока case following, по крайней мере, в моем примере одного. - person Jerry Krinock; 28.05.2015

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

person Flyingdiver    schedule 26.09.2011

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

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

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

person Vincent    schedule 18.12.2014

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

NSDate *start = [NSDate date];

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

person Z. Zepos    schedule 05.12.2012
comment
То же самое; ошибка в середине. Мне нужно было только переместить объявление переменной над переключателем (это не зависело от регистра). Мне не пришлось добавлять скобки вокруг корпуса (на этот раз). - person eGanges; 13.02.2015

До:

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

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

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

}
person Roozbeh Zabihollahi    schedule 23.02.2014

Объявите переменные вне переключателя, а затем создайте их экземпляры внутри корпуса. Это отлично сработало для меня, используя Xcode 6.2

person user3433008    schedule 20.03.2015

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

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

person hemant_maverik    schedule 16.08.2012

Заключите фигурными скобками {} код между оператором case и break в каждом случае. Это сработало с моим кодом.

person David Vargas    schedule 12.08.2015