Ketika mengonversi proyek untuk menggunakan ARC, apa yang dimaksud dengan "sakelar kasus dalam cakupan terproteksi"?

283

Ketika mengonversi proyek untuk menggunakan ARC, apa yang dimaksud dengan "sakelar kasus dalam cakupan terproteksi"? Saya mengonversi proyek untuk menggunakan ARC, menggunakan Xcode 4 Edit -> Refactor -> Konversi ke Objective-C ARC ... Salah satu kesalahan yang saya dapatkan adalah "sakelar kasus dalam cakupan yang dilindungi" pada "beberapa" sakelar di kasus saklar.

Edit, Ini kodenya:

ERROR ditandai pada case "default":

- (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
sumber

Jawaban:

651

Kelilingi setiap peti itu sendiri dengan kawat gigi {}. Itu harus memperbaiki masalah (itu terjadi pada saya di salah satu proyek saya).

FeifanZ
sumber
12
Kawat gigi membantu kompiler memahami ruang lingkup. Saya tahu GCC biasa mengeluarkan peringatan jika Anda mendeklarasikan variabel baru di baris pertama pernyataan kasus tanpa kawat gigi, dan video WWDC 2011 di ARC menyebutkan sesuatu tentang melampirkan kasus dalam kawat gigi. Jika Anda ingin tahu alasannya, lihat video itu — saya tidak dapat mengingat bagian atas kepala saya.
FeifanZ
87
Sudah lama, tapi saya sepertinya mengingat sesuatu dalam standar C yang tidak memungkinkan penugasan variabel setelah pernyataan kasus karena kode tidak benar-benar di dalam blok. Dengan menambahkan kurung kurawal {...}setelah casedan sebelum break, semua yang ada di dalamnya berada dalam blok yang tertutup dan akan berperilaku seperti yang diharapkan. Saya sampai pada titik bahwa saya secara otomatis membuat blok dari casepernyataan saya untuk menghindari masalah semacam ini.
Paul
2
Saya mengalami masalah yang sama. Ini adalah pesan kesalahan yang mengerikan dan bug telah diajukan (yang akan diperbaiki di versi kompiler yang akan datang) untuk memperbaikinya. Tapi, ya, aturan pelingkupan dalam pernyataan kasus di C benar-benar ... aneh.
bbum
59
Ini terjadi karena Anda mendeklarasikan variabel baru dalam ruang lingkup suatu kasus. Kompiler tidak tahu bagaimana variabel ini harus dicakup (apakah itu milik semua kasus switch atau hanya kasus saat ini?) Membungkus implementasi kasus dalam tanda kurung menciptakan ruang lingkup untuk variabel untuk hidup dalam sehingga kompiler dapat mengelola dengan baik ini seumur hidup.
Shinohara
1
Perhatikan bahwa ini juga dapat terjadi ketika mendeklarasikan variabel dalam blok dalam pernyataan kasus tanpa kurung kurawal. Itu penggaruk kepala selama satu atau dua menit. =)
slycrel
14

Sulit untuk memastikan tanpa melihat kode, tetapi mungkin berarti ada beberapa deklarasi variabel yang terjadi di dalam saklar dan kompiler tidak dapat mengetahui apakah ada jalur yang jelas ke titik dealloc yang diperlukan.

Flyingdiver
sumber
9

Ada 2 cara mudah untuk mengatasi masalah ini:

  • Anda mungkin mendeklarasikan variabel. Pindahkan deklarasi variabel di luar pernyataan switch
  • Letakkan seluruh case block di antara kurung keriting {}

Kompiler tidak dapat menghitung baris kode ketika variabel akan dirilis. Menyebabkan kesalahan ini.

Vincent
sumber
5

Bagi saya, masalahnya dimulai di tengah sakelar dan kurung keriting tidak berhasil, kecuali Anda harus memasukkan {} DALAM SEMUA pernyataan kasus sebelumnya. Bagi saya kesalahan datang ketika saya memiliki pernyataan

NSDate *start = [NSDate date];

dalam kasus sebelumnya. Setelah saya menghapus ini, maka semua pernyataan kasus berikutnya menjadi bersih dari pesan kesalahan cakupan yang dilindungi

Z. Zepos
sumber
Hal yang sama; kesalahan huruf di tengah. Saya hanya perlu memindahkan deklarasi variabel di atas saklar (itu tidak tergantung kasus). Saya tidak perlu menambahkan kawat gigi di sekitar kasing (kali ini).
eGanges
3

Sebelum:

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

Saya memindahkan definisi NSDate sebelum beralih, dan memperbaiki masalah kompilasi:

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

}
Roozbeh Zabihollahi
sumber
2

Deklarasikan variabel di luar switch, lalu instantiate di dalam case. Itu bekerja dengan sempurna bagi saya menggunakan Xcode 6.2

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

Catatan: Periksa! Sintaks dari garis tebal & miring. Perbaiki itu dan Anda baik untuk pergi.

hemant_maverik
sumber
0

Dikelilingi dengan menguatkan {}kode antara pernyataan kasus dan istirahat di setiap kasus. Ini berhasil pada kode saya.

David Vargas
sumber