เมื่อแปลงโครงการเพื่อใช้ ARC“ กรณีสวิตช์อยู่ในขอบเขตที่ได้รับการป้องกัน” หมายความว่าอย่างไร


283

เมื่อแปลงโครงการเพื่อใช้ ARC "กรณีสวิตช์อยู่ในขอบเขตที่มีการป้องกัน" หมายความว่าอย่างไร ฉันกำลังแปลงโครงการเพื่อใช้ ARC โดยใช้ Xcode 4 Edit -> Refactor -> แปลงเป็น 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ทุกอย่างภายในอยู่ในบล็อก scoped และจะทำงานตามที่คาดไว้ ฉันได้รับจนถึงจุดที่ฉันเพิ่งสร้างบล็อกจากcaseคำสั่งของฉันโดยอัตโนมัติเพื่อหลีกเลี่ยงปัญหาชนิดนี้
พอล

2
ฉันพบปัญหาเดียวกัน มันเป็นข้อความแสดงข้อผิดพลาดที่น่ากลัวและมีการบันทึกข้อผิดพลาด (ซึ่งจะแก้ไขในคอมไพเลอร์เวอร์ชันในอนาคต) เพื่อแก้ไข แต่ใช่กฎการกำหนดขอบเขตภายในคำสั่งกรณีใน C จริงๆ ... แปลกมาก
bbum

59
สิ่งนี้เกิดขึ้นเพราะคุณกำลังประกาศตัวแปรใหม่ภายในขอบเขตของกรณี คอมไพเลอร์ไม่ทราบว่าตัวแปรนี้ควรถูกกำหนดขอบเขต (มันเป็นของทุกกรณีสวิทช์หรือเพียงแค่กรณีปัจจุบันหรือไม่) การตัดการใช้งานของเคสในวงเล็บสร้างขอบเขตสำหรับตัวแปรที่จะอยู่ภายในเพื่อให้คอมไพเลอร์สามารถจัดการได้อย่างเหมาะสม มันคืออายุการใช้งาน
ชิโนฮาระ

1
โปรดทราบว่าสิ่งนี้สามารถเกิดขึ้นได้เมื่อประกาศตัวแปรภายในบล็อกภายในคำสั่ง case โดยไม่มีเครื่องหมายปีกกา นั่นคือ scratcher หัวหนึ่งหรือสองนาที =)
slycrel

14

ยากที่จะแน่ใจโดยไม่ดูรหัส แต่อาจหมายความว่ามีการประกาศตัวแปรที่เกิดขึ้นภายในสวิตช์และคอมไพเลอร์ไม่สามารถบอกได้ว่ามีเส้นทางที่ชัดเจนไปยังจุด dealloc ที่ต้องการหรือไม่


9

มี 2 ​​วิธีง่าย ๆ ในการแก้ไขปัญหานี้:

  • คุณอาจประกาศตัวแปร ย้ายการประกาศของตัวแปรภายนอกคำสั่ง switch
  • ใส่บล็อกตัวเรือนทั้งตัวระหว่างวงเล็บปีกกา {}

คอมไพเลอร์ไม่สามารถคำนวณบรรทัดโค้ดได้เมื่อมีการปล่อยตัวแปร ทำให้เกิดข้อผิดพลาดนี้


5

สำหรับฉันปัญหาเริ่มต้นที่จุดกึ่งกลางของสวิตช์และวงเล็บปีกกาไม่ได้ผลเว้นแต่คุณจะต้องรวม {} ในคำสั่งกรณีก่อนหน้าทั้งหมด สำหรับฉันข้อผิดพลาดมาเมื่อฉันมีคำสั่ง

NSDate *start = [NSDate date];

ในกรณีก่อนหน้า หลังจากที่ฉันลบสิ่งนี้คำสั่งเคสที่ตามมาทั้งหมดจะสะอาดจากข้อความแสดงข้อผิดพลาดของขอบเขตที่ได้รับการป้องกัน


สิ่งเดียวกัน; ข้อผิดพลาดกรณีที่อยู่ตรงกลาง ฉันแค่ต้องย้ายการประกาศตัวแปรเหนือสวิตช์ (มันไม่ได้ขึ้นอยู่กับกรณี) ฉันไม่จำเป็นต้องเพิ่มเครื่องมือจัดฟันรอบเคส (คราวนี้)
eGanges

3

ก่อน:

    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;

}

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และตัวแบ่งในแต่ละกรณี มันทำงานกับรหัสของฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.