Kegagalan pernyataan di - [UITableView _endCellAnimationsWithContext:]

89

Semoga ini menjadi perbaikan yang cepat. Saya telah mencoba mencari tahu kesalahan yang terus saya dapatkan. Kesalahannya tercantum di bawah dan appdelagate ada di bawahnya.

Setiap bantuan dihargai.

Terima kasih

2012-04-12 21: 11: 52.669 Chanda [75100: f803] --- Kegagalan pernyataan di -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037 2012-04-12 21: 11: 52.671 Chanda [75100: f803] --- Menghentikan aplikasi karena pengecualian yang tidak tertangkap ' NSInternalInconsistencyException' , alasan: 'Pembaruan tidak valid: jumlah baris tidak valid di bagian 0. Jumlah baris yang ada di bagian yang ada setelah pembaruan (2) harus sama dengan jumlah baris yang ada di bagian itu sebelum pembaruan (2), ditambah atau minus jumlah baris yang disisipkan atau dihapus dari bagian itu (1 disisipkan, 0 dihapus) dan plus atau minus jumlah baris yang dipindahkan masuk atau keluar dari bagian itu (0 pindah masuk, 0 pindah keluar). '

#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
Scubadivingfool
sumber
3
Anda harus memindahkan kode itu ke kelas dan mungkin mengeksekusinya di thread latar belakang. Bagaimanapun, kesalahan ini biasanya muncul saat Anda mencoba menghapus baris tanpa benar-benar mengurangi jumlah baris seperti yang disediakan oleh sumber data tampilan tabel. Apakah Anda benar-benar menghapus data saat Anda menghapus baris? Jika Anda tidak menghapus baris apa pun, dapatkah Anda memberikan penerapan sumber data tampilan tabel?
Constantino Tsarouhas

Jawaban:

43

Saya tidak melihat alasan Anda menunjukkan bagian kode ini kepada kami. Kesalahan Anda harus terhubung ke bagian ini dalam kode Anda, saya asumsikan

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

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

Mungkin Anda membuat kesalahan dalam salah satu metode sumber data ini. Saat ini tidak mungkin untuk mengatakan apa yang sebenarnya salah tetapi saya berasumsi itu bisa seperti: Anda memberi tahu tampilan tabel di numberOfRowsInSectionAnda ingin memiliki n baris yang dipesan dan disiapkan dan di cellForRowAtIndexPathAnda hanya menangani n - 1 baris misalnya.

Maaf, jawaban ini tidak bisa setepat yang seharusnya. Jika Anda menunjukkan kepada kami penerapan sumber data Anda, akan lebih mudah untuk mengetahui apa yang terjadi.

pbx
sumber
26

Seperti yang dikatakan Sun Tzu : yang terbaik adalah menang tanpa bertengkar . Dalam kasus saya setiap kali saya melihat pesan kesalahan semacam ini (yaitu perbedaan antara baris yang ditambahkan dihapus dll) .. Saya bahkan tidak men-debug apa pun .. Saya hanya menghindari membuat panggilan tambahan di mana saya memuat ulang baris dll .. itu 99% dari kasus di mana kesalahan ini terjadi.

Ini adalah skenario umum di mana bug ini terjadi: Saya punya UINavigationControllerdan memiliki UITableView, ketika saya mengklik baris itu mendorong yang baru UITableViewdan seterusnya. Kesalahan ini selalu terjadi pada saya ketika saya memunculkan yang terakhir UITableviewdan kembali ke UITableViewsebelumnya, pada titik ini saya membuat panggilan yang tidak perlu ke loadItfungsi yang pada dasarnya menyisipkan baris dan relaods UITableView.

Alasan hal ini terjadi adalah karena saya salah menempatkan fungsi loadIt saya viewDidAppear:animateddaripada viewDidLoad. viewDidAppear:animateddipanggil setiap kali UITableViewditampilkan, viewDidLoadhanya dipanggil sekali.

biara
sumber
3
Terima kasih, kata yang bagus. Paragraf pertama Anda menempatkan saya di jalur yang benar untuk memecahkan masalah serupa.
scrrr
2
dengan senang hati @scrrr :)
abbood
Ini mengubah cara saya melihatnya - ini memperbaiki masalah dengan membuatnya tidak relevan. Kamu keren!
Charlie
Kudos to viewDidAppear daripada viewDidLoad. Itulah masalah saya dan saya menanganinya selama berminggu-minggu.
GrandSteph
1
Saya mencetak kutipan Sun Tzu Anda dan menempelkannya di bagian atas layar saya. Terima kasih atas kutipannya dan membantu saya menemukan banyak kode yang berlebihan :)
Adrian
24

Saat menghapus baris, ingatlah bahwa itu juga memeriksa bagian saat memperbarui, di:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView

Jika Anda ingin menghapus baris yang merupakan item terakhir di suatu bagian, Anda perlu menghapus seluruh bagian sebagai gantinya (jika tidak, mungkin akan salah menghitung bagian dan membuang pengecualian ini).

Olof_t
sumber
1
Ini emas murni! Paku di kepala! Persis masalah saya.
phatmann
6

Jangan lupa untuk memperbarui larik Anda yang menentukan numberOfRowsInSection. Ini perlu diperbarui sebelum Anda menghidupkan dan menghapus

Kami memeriksa apakah jumlah baris di bagian adalah 1 karena kami harus menghapus seluruh bagian.

Lakukan koreksi saya jika ada yang bisa membuat jawaban ini lebih jelas.

[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];
love2script12
sumber
4

Saya menempatkan setiap elemen bagian dalam array terpisah. Kemudian masukkan ke dalam array lain (arrayWithArray). Solusi saya di sini untuk masalah ini:

[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];
Bob
sumber
1
bagi saya itu adalah pembaruan awal dan akhir yang menyelesaikannya, terima kasih!
Mark W
2
Saya tidak tahu bahwa bagian tersebut menjadi kosong dan kebutuhan untuk menghidupkannya sebagai gantinya ... Sial! Terima kasih!
dvkch
1
Punya kode saya untuk bekerja dengan banyak bantuan dari jawaban ini. Posting di bawah.
love2script12
2

Saya mengalami kesalahan yang sama.

Saya menggunakan baris berikut

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

untuk mendaftarkan ujung pena dalam metode viewDidLoad, karena saya memiliki ujung yang berbeda yang juga terkait dengan kelas yang sama. Oleh karena itu, garisnya

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

kembali nihil kecuali saya mendaftarkan nib di viewDidLoad.

Masalah saya adalah bahwa saya lupa menyetel pengenal di inspektur atribut untuk file saya "CustomNib.xib" dan "CustomNib ~ iphone.xib". (Atau lebih tepatnya, saya lupa menekan enter setelah mengetik pengenal di inspektur atribut di XCode, sehingga nama baru gagal disimpan.)

Semoga ini membantu.

pengguna1612868
sumber
2
Saya TIDAK berpikir bahwa jawaban Anda ada hubungannya dengan masalah ini.
DawnSong
2

Jika Anda menggunakan NSFetchedResultsControllerlike me dan mengupdate data di thread latar belakang, jangan lupa untuk memulai dan mengakhiri update di delegasi:

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

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

Saya mengalami kesalahan yang sama, yang ketika mencoba [tableView reloadData]bekerja dengan baik. Kesalahan sebenarnya ada di telepon

[TabView insertRowsAtIndexPaths:indexPathsArray withRowAnimation:UITableViewRowAnimationRight];

Ketika saya mencoba untuk memeriksa nilai indexPath, mereka tidak benar seperti yang disyaratkan.

Saya memperbaikinya dengan mengubah nilai dalam indexPathsArray.

Semoga ini membantu .

pengguna5553647
sumber
1

Ini bisa menjadi salah satu UITableViewDataSourcemetode protokol

Untuk

- tableView:numberOfRowsInSection:

itu harus mengembalikan integer sama dengan jumlah atau hasil

-insertRowsAtIndexPaths:withRowAnimation:dan / atau -deleteRowsAtIndexPaths:withRowAnimation:

Untuk

- numberOfSectionsInTableView:

itu harus mengembalikan integer yang sama dengan jumlah atau hasil

-insertRowsAtIndexPaths:withRowAnimation: dan / atau -deleteSections:withRowAnimation:

Ted
sumber
0

Saya memiliki masalah yang sama dengan Core Data base. Jika Anda menggunakan banyak FRC, Anda hanya perlu memuat ulang tampilan tabel di dalam setiap kondisi di numberOfSectionsInTableView.

Privatus Privatus
sumber
2
Saya juga memiliki masalah ini dengan Data Inti. Bisakah Anda jelaskan resep Anda.
Drux
0

Saya baru saja mengalami hal ini saat menggunakan Swift dan penyimpanan data yang didukung FRC untuk mengelola informasi. Menambahkan pemeriksaan sederhana ke operasi delete untuk mengevaluasi indexPath.section saat ini memungkinkan saya menghindari panggilan asing. Saya rasa saya mengerti mengapa masalah ini terjadi ... Pada dasarnya saya memuat pesan ke baris atas setiap kali dataset saya kosong. Ini menciptakan masalah off demi satu karena ada baris palsu.

Solusi Saya

... 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)

            }
Tommie C.
sumber
0

Cukup periksa apakah Anda memanggil [yourTableView reloadData]; setelah memodifikasi larik nilai.

Evgeniy Kleban
sumber