การยืนยันล้มเหลวใน - [UITableView _endCellAnimationsWithContext:]


89

หวังว่านี่จะเป็นการแก้ไขโดยเร็ว ฉันพยายามหาข้อผิดพลาดที่ได้รับเรื่อย ๆ ข้อผิดพลาดแสดงอยู่ด้านล่างและ appdelagate อยู่ด้านล่าง

ขอความช่วยเหลือใด ๆ

ขอบคุณ

2012-04-12 21: 11: 52.669 Chanda [75100: f803] --- การยืนยันล้มเหลวใน-[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037 2012-04-12 21: 11: 52.671 Chanda [75100: f803] --- การยุติแอปเนื่องจากข้อยกเว้นที่ไม่ได้ตรวจพบ ' NSInternalInconsistencyException' , เหตุผล: 'การอัปเดตไม่ถูกต้อง: จำนวนแถวที่ไม่ถูกต้องในส่วน 0 จำนวนแถวที่มีอยู่ในส่วนที่มีอยู่หลังจากการอัปเดต (2) ต้องเท่ากับจำนวนแถวที่อยู่ในส่วนนั้นก่อนการอัปเดต (2) บวก หรือลบจำนวนแถวที่แทรกหรือลบออกจากส่วนนั้น (แทรก 1 รายการลบ 0) และบวกหรือลบจำนวนแถวที่ย้ายเข้าหรือออกจากส่วนนั้น (0 ย้ายเข้า 0 ย้ายออก) '

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize databaseName,databasePath; 

- (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
    self.databaseName = @"Customers.db";

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDir = [documentPaths objectAtIndex:0];
    self.databasePath = [documentDir stringByAppendingPathComponent:self.databaseName];
    [self createAndCheckDatabase];

    return YES;
}

- (void)createAndCheckDatabase {
    BOOL success;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    success = [fileManager fileExistsAtPath:databasePath];

    if (success) return; 

    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];

    [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}

@end

3
คุณควรย้ายรหัสนั้นไปที่คลาสและอาจเรียกใช้งานในเธรดพื้นหลัง อย่างไรก็ตามข้อผิดพลาดนี้มักเกิดขึ้นเมื่อคุณพยายามลบแถวโดยไม่ลดจำนวนแถวตามที่แหล่งข้อมูลของมุมมองตารางให้มา คุณกำลังลบข้อมูลจริง ๆ เมื่อคุณลบแถว? หากคุณไม่ได้ลบแถวใด ๆ คุณสามารถใช้แหล่งข้อมูลมุมมองตารางได้หรือไม่
Constantino Tsarouhas

คำตอบ:


43

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

คุณอาจทำผิดพลาดในวิธีการแหล่งข้อมูลเหล่านี้ ขณะนี้เป็นไปไม่ได้ที่จะพูดว่าอะไรผิดปกติ แต่ฉันคิดว่ามันอาจเป็นเช่น: คุณกำลังบอกมุมมองตารางในรายการที่numberOfRowsInSectionคุณต้องการสงวนและตั้งค่าnแถวcellForRowAtIndexPathจากนั้นคุณจะจัดการเฉพาะn - 1แถว

ขออภัยที่คำตอบนี้ไม่แม่นยำเท่าที่ควร หากคุณแสดงให้เราเห็นถึงการใช้งานแหล่งข้อมูลของคุณคุณจะบอกได้ง่ายกว่ามากว่าเกิดอะไรขึ้น


26

เช่นเดียวกับซุนวูกล่าวว่า : ดีที่สุดที่จะชนะโดยไม่ต้องต่อสู้ ในกรณีของฉันเมื่อใดก็ตามที่ฉันเห็นข้อความแสดงข้อผิดพลาดประเภทนี้ (เช่นความคลาดเคลื่อนระหว่างแถวที่เพิ่มถูกลบ ฯลฯ ) .. ฉันไม่ได้แก้จุดบกพร่องอะไรเลย .. ฉันเพียงแค่หลีกเลี่ยงการโทรพิเศษนั้นโดยที่ฉันโหลดแถวซ้ำเป็นต้นนั่นคือ 99% ของ กรณีที่เกิดข้อผิดพลาดนี้

นี่เป็นสถานการณ์ทั่วไปที่เกิดข้อผิดพลาดนี้: ฉันมีUINavigationControllerและมันมีUITableViewเมื่อฉันคลิกที่แถวมันจะผลักดันใหม่UITableViewและอื่น ๆ ข้อผิดพลาดนี้เกิดขึ้นกับฉันเสมอเมื่อฉันป๊อปอัพครั้งสุดท้ายUITableviewและย้อนกลับไปUITableViewก่อนหน้านั้น ณ จุดนี้ฉันทำการเรียกใช้loadItฟังก์ชันที่ไม่จำเป็นซึ่งโดยทั่วไปจะแทรกแถวและเปิดไฟล์UITableView.

เหตุนี้เกิดขึ้นเป็นเพราะฉันไม่สมควรวางฟังก์ชั่น loadIt ของฉันในมากกว่าviewDidAppear:animated จะถูกเรียกทุกครั้งที่แสดงจะถูกเรียกเพียงครั้งเดียวviewDidLoadviewDidAppear:animatedUITableViewviewDidLoad


3
ขอบคุณพูดดี ย่อหน้าแรกของคุณทำให้ฉันมาถูกทางในการแก้ปัญหาที่คล้ายกัน
scrrr

2
เป็นความสุขของฉัน @scrrr :)
abbood

สิ่งนี้เปลี่ยนวิธีที่ฉันมองไป - มันแก้ไขปัญหาโดยทำให้ไม่เกี่ยวข้อง คุณร็อค!
Charlie

ชื่นชอบเพื่อ viewDidAppear มากกว่า viewDidLoad นั่นเป็นปัญหาของฉันและฉันก็จัดการกับมันมาหลายสัปดาห์แล้ว
GrandSteph

1
ฉันพิมพ์คำพูดซุนวูของคุณและบันทึกไว้ที่ด้านบนของหน้าจอ ขอบคุณสำหรับคำพูดและการช่วยเหลือฉันในการค้นหารหัสซ้ำซ้อนจำนวนมาก :)
Adrian

24

เมื่อลบแถวอย่าลืมว่าจะตรวจสอบส่วนต่างๆเมื่ออัปเดตใน:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView

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


1
นี่คือทองคำแท้! ตะปูฟาดหัว! ตรงประเด็นของฉัน
phatmann

6

อย่าลืมอัปเดตอาร์เรย์ของคุณซึ่งกำหนด numberOfRowsInSection ต้องมีการอัปเดตก่อนที่คุณจะเคลื่อนไหวและนำออก

เราตรวจสอบว่าจำนวนแถวในส่วนคือ 1 หรือไม่เพราะเราจะต้องลบทั้งส่วน

โปรดแก้ไขฉันหากใครสามารถทำให้คำตอบนี้ชัดเจนขึ้น

[self.tableView beginUpdates];
if ([tableView numberOfRowsInSection:indexPath.section] == 1) {

   [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {

   [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView endUpdates];

4

ฉันใส่องค์ประกอบแต่ละส่วนในอาร์เรย์ที่แยกจากกัน จากนั้นใส่ลงในอาร์เรย์อื่น (arrayWithArray) ทางออกของฉันสำหรับปัญหานี้:

[quarantineMessages removeObject : message];
[_tableView beginUpdates];
if([[arrayWithArray objectAtIndex: indPath.section] count]  > 1)
{
    [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indPath] withRowAnimation:UITableViewRowAnimationBottom];
}
else
{
    [_tableView deleteSections:[NSIndexSet indexSetWithIndex:indPath.section]
              withRowAnimation:UITableViewRowAnimationFade];
}
[_tableView endUpdates];

1
สำหรับฉันมันเป็นการอัปเดตเริ่มต้นและสิ้นสุดที่แก้ไขได้ขอบคุณ!
Mark W

2
ฉันไม่รู้ว่าเกี่ยวกับส่วนนั้นว่างเปล่าและจำเป็นต้องทำให้มันเคลื่อนไหวแทน ... ให้ตายเถอะ! ขอบคุณ!
dvkch

1
ขอให้รหัสของฉันทำงานได้ด้วยความช่วยเหลือมากมายจากคำตอบนี้ โพสต์ไว้ด้านล่าง
love2script12

2

ฉันมีข้อผิดพลาดเดียวกัน

ฉันใช้บรรทัดต่อไปนี้

UINib *myCustomCellNib = [UINib nibWithNibName:@"CustomNib" bundle:nil];
[tableView registerNib:myCustomCellNib forCellReuseIdentifier:@"CustomNib"];

เพื่อลงทะเบียน nib ในเมธอด viewDidLoad เนื่องจากฉันมีหัวปากกาอื่นที่เชื่อมโยงกับคลาสเดียวกันด้วย ดังนั้นบรรทัด

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GBFBLoadingCell"];

กำลังส่งคืนศูนย์เว้นแต่ฉันจะลงทะเบียนหัวปากกาใน viewDidLoad

ปัญหาของฉันคือฉันลืมตั้งค่าตัวระบุในตัวตรวจสอบแอตทริบิวต์สำหรับไฟล์ "CustomNib.xib" และ "CustomNib ~ iphone.xib" (หรืออย่างแม่นยำกว่านั้นคือฉันลืมกด Enter หลังจากพิมพ์ตัวระบุในตัวตรวจสอบแอตทริบิวต์ใน XCode เพื่อไม่ให้บันทึกชื่อใหม่)

หวังว่านี่จะช่วยได้


2
ฉันไม่คิดว่าคำตอบของคุณเกี่ยวข้องกับปัญหานี้
DawnSong

2

หากคุณใช้NSFetchedResultsControllerเหมือนฉันและอัปเดตข้อมูลในเธรดพื้นหลังอย่าลืมเริ่มต้นและสิ้นสุดการอัปเดตในผู้รับมอบสิทธิ์:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

2

ฉันมีข้อผิดพลาดเดียวกันซึ่งเมื่อลองใช้งาน[tableView reloadData]ก็ใช้ได้ดี ข้อผิดพลาดเกิดขึ้นจริงในบรรทัด

[TabView insertRowsAtIndexPaths:indexPathsArray withRowAnimation:UITableViewRowAnimationRight];

เมื่อฉันพยายามตรวจสอบค่า indexPath พวกเขาไม่ถูกต้องตามที่กำหนด

ฉันแก้ไขโดยเปลี่ยนค่าในindexPathsArray.

หวังว่านี่จะช่วยได้


1

อาจเป็นหนึ่งในUITableViewDataSourceวิธีโปรโตคอล

สำหรับ

- tableView:numberOfRowsInSection:

ควรส่งคืนจำนวนเต็มเท่ากับผลรวมหรือผลลัพธ์ของ

-insertRowsAtIndexPaths:withRowAnimation:และ / หรือ-deleteRowsAtIndexPaths:withRowAnimation:

สำหรับ

- numberOfSectionsInTableView:

ควรส่งคืนจำนวนเต็มเท่ากับผลรวมหรือผลลัพธ์ของ

-insertRowsAtIndexPaths:withRowAnimation: และ / หรือ -deleteSections:withRowAnimation:


0

ฉันมีปัญหาเดียวกันกับฐานข้อมูลหลัก หากคุณใช้ FRC จำนวนมากคุณเพียงแค่ต้องโหลด tableview ซ้ำภายในแต่ละเงื่อนไขใน numberOfSectionsInTableView


2
ฉันมีปัญหากับ Core Data ด้วย คุณช่วยอธิบายสูตรของคุณอย่างละเอียดได้ไหม
Drux

0

ฉันเพิ่งเกิดเหตุการณ์นี้ขึ้นกับฉันในขณะที่ใช้ Swift และที่เก็บข้อมูลที่สำรองไว้ของ FRC เพื่อจัดการข้อมูล การเพิ่มการตรวจสอบอย่างง่ายในการดำเนินการลบเพื่อประเมิน indexPath.section ปัจจุบันทำให้ฉันสามารถหลีกเลี่ยงการเรียกที่ไม่เกี่ยวข้องได้ ฉันคิดว่าฉันเข้าใจว่าทำไมปัญหานี้จึงเกิดขึ้น ... โดยทั่วไปฉันโหลดข้อความในแถวบนสุดเมื่อใดก็ตามที่ชุดข้อมูลของฉันว่างเปล่า สิ่งนี้ทำให้เกิดการปิดทีละประเด็นเนื่องจากมีแถวที่ไม่เหมาะสม

โซลูชันของฉัน

... delete my entity, save the datastore and call reloadData on tableView
//next I add this simple check to avoid calling deleteRows when the system (wrongly) determines that there is no section.

       if indexPath.section > 0 {

        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .None)

            }

0

เพียงตรวจสอบว่าคุณเรียก [yourTableView reloadData]; หลังจากแก้ไขอาร์เรย์ของค่า

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