Pernyataan kegagalan dalam dequeueReusableCellWithIdentifier: forIndexPath:

324

Jadi saya membuat rss reader untuk sekolah saya dan menyelesaikan kode. Saya menjalankan tes dan itu memberi saya kesalahan itu. Berikut adalah kode yang dimaksud:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = 
     [tableView dequeueReusableCellWithIdentifier:CellIdentifier 
                                     forIndexPath:indexPath];
    if (cell == nil) {

        cell = 
         [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  
                                reuseIdentifier:CellIdentifier];

    }

inilah kesalahan dalam output:

2012-10-04 20: 13: 05.356 Pembaca [4390: c07] * Kegagalan pernyataan dalam - [UITableView dequeueReusableCellWithIdentifier: forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460 2012-10-04 20: 10-10 13: 05.357 Pembaca [4390: c07] * Mengakhiri aplikasi karena pengecualian tanpa tertangkap 'NSInternalInconsistencyException', alasan: 'tidak dapat membuat sel dengan pengenal Sel - harus mendaftarkan nib atau kelas untuk pengidentifikasi atau menyambungkan sel prototipe dalam storyboard ' * Pertama tumpukan lemparan panggilan: (0x1c91012 0x10cee7e 0x1c90e78 0xb64f35 0xc7d14 0x39ff 0xd0f4b 0xd101f 0xb980b 0xca19b 0x6692d 0x10e26b0 0x228dfc0 0x228233c 0x228deaf 0x1058cd 0x4e1a6 0x4ccbf 0x4cbd9 0x4be34 0x4bc6e 0x4ca29 0x4f922 0xf9fec 0x46bc4 0x47311 0x2cf3 0x137b7 0x13da7 0x14fab 0x26315 0x2724b 0x18cf8 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x147da 0x1665c 0x2a02 0x2935 ) libc ++ abi.dylib: terminate disebut throwing exception

dan inilah kode yang ditampilkan di layar kesalahan:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

tolong bantu!

Nick Scottman
sumber

Jawaban:

488

Anda menggunakan dequeueReusableCellWithIdentifier:forIndexPath:metode ini. The dokumentasi untuk metode yang mengatakan ini:

Penting: Anda harus mendaftarkan file kelas atau nib menggunakan metode registerNib:forCellReuseIdentifier:atau registerClass:forCellReuseIdentifier:sebelum memanggil metode ini.

Anda tidak mendaftarkan nib atau kelas untuk pengidentifikasi ulang "Cell".

Melihat kode Anda, Anda tampaknya mengharapkan metode dequeue untuk kembali niljika tidak memiliki sel untuk memberi Anda. Anda perlu menggunakan dequeueReusableCellWithIdentifier:untuk perilaku itu:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Perhatikan itu dequeueReusableCellWithIdentifier:dan dequeueReusableCellWithIdentifier:forIndexPath:merupakan metode yang berbeda. Lihat dokumen untuk yang pertama dan yang terakhir .

Jika Anda ingin memahami mengapa Anda ingin menggunakannya dequeueReusableCellWithIdentifier:forIndexPath:, lihat T&J ini .

rob mayoff
sumber
166
OH TUHAN. Mengapa templat default Xcode untuk UITableViewController secara otomatis memberi Anda dequeueReusableCellWithIdentifier: forIndexPath :? Sangat tidak membantu.
spstanley
15
The dequeueReusableCellWithIdentifer:forIndexPath:(diperkenalkan di iOS6) adalah perbaikan bagus, karena Anda tidak perlu memeriksa apakah sel adalah nihil. (Jadi UITableViewControllerberfungsi mirip dengan UICollectionView) Tapi ya, mengganggu bahwa perubahan ini tidak mengomentari template dan bahwa pesan pernyataan / kerusakan tidak lebih membantu.
Jason Moore
2
Paling tidak Anda akan berpikir bahwa itu akan default ke UITableViewCell bukannya meledak. Baka.
BadPirate
13
Baris terakhir dari jawaban ini adalah emas: Saya telah digigit lebih dari satu kali dengan menggunakan dequeueReusableCellWithIdentifier:forIndexPath:saat saya seharusnya menggunakan dequeueReusableCellWithIdentifier:.
ele
Jawaban ini sempurna. Saya punya pertanyaan: Saya punya tableViewController sebagai pengendali tampilan awal saya. Di didSelectRow ... Saya mendorong tableViewController lain ke tumpukan navigasi. Kenapa saya hanya perlu mendaftarkan sel untuk tableViewController kedua, bukan yang pertama?
ArielSD
137

Saya pikir kesalahan ini adalah tentang mendaftarkan nib atau kelas Anda untuk pengidentifikasi.

Sehingga Anda dapat menyimpan apa yang Anda lakukan dalam fungsi tableView: cellForRowAtIndexPath Anda dan cukup tambahkan kode di bawah ini ke dalam viewDidLoad Anda:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Ini berhasil untuk saya. Semoga ini bisa membantu.


sumber
3
Satu gotcha kecil dengan ini - pastikan pengidentifikasi ulang cocok dengan apa yang telah Anda atur di pengaturan Storyboard Anda untuk sel yang dimaksud.
James Boutcher
Hanya untuk menambahkan ini pada use case yang sedikit berbeda, saya memilih ulang baris dalam tampilan Master SplitViewController saya. Pilih kembali logika baris ini di viewDidLoaddan pindahkan logika ini untuk viewDidAppearmemperbaikinya.
Craig Conover
Itu tidak bisa masuk dalam sel == nil, Jadi sel tableview saya selalu nihil.
Solid Soft
3
swift 3.0: self.tableView.register (UITableViewCell.classForCoder (), forCellReuseIdentifier: "Cell");
norbDEV
68

Meskipun pertanyaan ini cukup lama, ada kemungkinan lain: Jika Anda menggunakan Storyboard, Anda hanya perlu mengatur CellIdentifier di Storyboard.

Jadi jika CellIdentifier Anda adalah "Cell", cukup setel properti "Identifier": masukkan deskripsi gambar di sini

Pastikan untuk membersihkan bangunan Anda setelah melakukannya. XCode terkadang memiliki beberapa masalah dengan pembaruan Storyboard

Sebastian Borggrewe
sumber
3
Anda hebat, membersihkan banyak hal !! : D
Sandy
2
Catatan - jika Anda menggunakan pengenal selain "Sel" Anda juga harus mengubah metode cellForRowAtIndexPath Anda untuk menggunakan pengenal ini pada baris berikut: NSString statis * CellIdentifier = @ "MyCellIdentifier";
gamozzii
5
Satu tambahan penting untuk ini: Tampilan tabel harus memiliki atribut "Content" yang disetel ke "Dynamic Prototypes", BUKAN "Static Cells"
Ted Avery
Jawaban ini harus lebih tinggi. Sangat membantu
Sukitha Udugamasooriya
Membangun pembersihan sangat penting setelah memperbarui Identifierproperti. Terima kasih!
Crashalot
59

saya memiliki masalah yang sama untuk diganti

static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

   if (cell==nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    }

terpecahkan

iMeMyself
sumber
Terima kasih. Ini baru saja menyelamatkan saya dari sakit kepala. =)
Robert
3
tip: jika Anda menggunakan - (id) dequeueReusableCellWithIdentifier: forIndexPath:, tidak perlu memverifikasi apakah sel nil. (IOS6>)
seufagner
baru saja menyelamatkan saya sakit kepala. =)
Abo3atef
26

Masalahnya kemungkinan besar karena Anda mengkonfigurasi custom UITableViewCelldi storyboard tetapi Anda tidak menggunakan storyboard untuk instantiate Anda UITableViewControlleryang menggunakan ini UITableViewCell. Misalnya, di MainStoryboard, Anda memiliki UITableViewControllersubkelas yang dipanggil MyTableViewControllerdan memiliki dinamik kustom yang UITableViewCelldisebut MyTableViewCelldengan id pengenal "MyCell".

Jika Anda membuat custom UITableViewControllerseperti ini:

 MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];

Itu tidak akan secara otomatis mendaftarkan tableviewcell kustom Anda untuk Anda. Anda harus mendaftarkannya secara manual.

Tetapi jika Anda menggunakan storyboard untuk instantiate MyTableViewController, seperti ini:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyTableViewController *myTableViewController = [storyboard  instantiateViewControllerWithIdentifier:@"MyTableViewController"];

Hal yang menyenangkan terjadi! UITableViewControllerakan secara otomatis mendaftarkan sel tampilan tabel kustom Anda yang Anda tetapkan dalam storyboard untuk Anda.

Dalam metode delegasi Anda "cellForRowAtIndexPath", Anda bisa membuat Anda sel tampilan tabel seperti ini:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

//Configure your cell here ...

return cell;
}

dequeueReusableCellWithIdentifier akan secara otomatis membuat sel baru untuk Anda jika tidak ada sel yang dapat digunakan kembali tersedia dalam antrian daur ulang.

Lalu kamu selesai!

James Wang
sumber
Tip yang digunakan instantiateViewControllerWithIdentifieruntuk init viewController saya menyelamatkan hari saya!
Lei Zhang
menyelamatkan hari saya: sel-sel prototipe berada di VC tetangga dengan sebuah meja
Anton Tropashko
Ini adalah alasan yang masuk akal dalam kasus saya.
Nora Alnashwan
19

Saya hanya akan menambahkan bahwa Xcode 4.5 menyertakan yang baru dequeueReusableCellWithIdentifier:forIndexPath:
dalam kode templat default - suatu gotcha potensial bagi para pengembang yang mengharapkan dequeueReusableCellWithIdentifier:metode yang lebih lama .

Brian Shriver
sumber
Menyengat saya! Sekarang saya akan tahu lebih baik. ;)
spstanley
18

Di storyboard Anda, Anda harus mengatur 'Identifier' dari sel prototipe Anda menjadi sama dengan CellReuseIdentifier Anda "Sel". Maka Anda tidak akan mendapatkan pesan itu atau perlu memanggil fungsi registerClass:.

Steven
sumber
2
Kena kau! Di mana tombol '100 upvotes'? Ini solusi nyata.
Jojo.Lechelt
Anda akan berpikir bahwa menambahkan tableView baru ke dalam storyboard akan memberikan pengidentifikasi default - 'Cell' untuk Anda. Ini sangat mudah diabaikan terutama jika Anda menggunakan 'kode bebas' yang disebut di tableView: cellForRowAtIndexPath!
ushika
18

Solusi Swift 2.0:

Anda harus masuk ke Inspektur Atribut dan menambahkan nama untuk Pengidentifikasi sel Anda:

masukkan deskripsi gambar di sini

Maka Anda perlu membuat identifier Anda cocok dengan dequeue Anda seperti ini:

let cell2 = tableView.dequeueReusableCellWithIdentifier("ButtonCell", forIndexPath: indexPath) as! ButtonCell

kalau tidak

Jika Anda bekerja dengan nib, Anda mungkin perlu mendaftarkan kelas di cellForRowAtIndexPath Anda:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {       

    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "SwitchCell")

    // included for context            
    let cell = tableView.dequeueReusableCellWithIdentifier("SwitchCell", forIndexPath:indexPath) as! SwitchCell

    //... continue    
}

Referensi Kelas UITableView dari Apples mengatakan:

Sebelum menghapus sel apa pun, panggil metode ini atau registerNib: forCellReuseIdentifier: metode untuk memberi tahu tampilan tabel cara membuat sel baru. Jika sel dari jenis yang ditentukan saat ini tidak dalam antrian penggunaan kembali, tampilan tabel menggunakan informasi yang disediakan untuk membuat objek sel baru secara otomatis.

Jika sebelumnya Anda mendaftarkan file kelas atau nib dengan pengidentifikasi ulang yang sama, kelas yang Anda tentukan dalam parameter cellClass menggantikan entri lama. Anda dapat menentukan nil untuk cellClass jika Anda ingin membatalkan registrasi kelas dari pengidentifikasi ulang yang ditentukan.

Berikut kode dari kerangka kerja Apples Swift 2.0:

// Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.

@available(iOS 5.0, *)
func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String)

@available(iOS 6.0, *)
func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
Dan Beaulieu
sumber
Saya tidak mengerti dari mana SwitchCell.selfdatangnya?
Gert Cuykens
@GertCuykens SwitchCell adalah UITableViewCell khusus saya
Dan Beaulieu
1
Saya jauh dari Mac saya sekarang, tetapi saya pasti dapat memperbaruinya ketika saya pulang.
Dan Beaulieu
1
Menggantinya dengan UITableViewCell.selftampaknya berfungsi untuk saya. Mungkin tambahkan catatan dalam jawaban
Gert Cuykens
@GertCuykens terima kasih untuk menunjukkan hal itu, saya telah mengubah SwitchCell.self untuk UITableViewCell.self
Dan Beaulieu
3

Jika Anda menggunakan Custom Static Cells, beri komentar metode ini:

//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//    static NSString *CellIdentifier = @"notificationCell";
//    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//    return cell;
//}

dan berikan sel pengenal di "Attributes Inspector" di storyboard.

Francisco Gutiérrez
sumber
3

Saya memberi Anda jawaban di Objective C dan Swift. Sebelum itu saya ingin mengatakan

Jika kita menggunakan dequeueReusableCellWithIdentifier:forIndexPath:, kita harus mendaftarkan file kelas atau nib menggunakan registerNib: forCellReuseIdentifier: atau registerClass: forCellReuseIdentifier: metode sebelum memanggil metode ini sebagai Apple Documnetation Says

Jadi kami menambahkan registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

Setelah kami mendaftarkan kelas untuk pengenal yang ditentukan dan sel baru harus dibuat, metode ini menginisialisasi sel dengan memanggil initWithStyle: reuseIdentifier: metode. Untuk sel berbasis nib, metode ini memuat objek sel dari file nib yang disediakan. Jika sel yang ada tersedia untuk digunakan kembali, metode ini akan memanggil metode prepForReuse sel.

dalam metode viewDidLoad kita harus mendaftarkan sel

Tujuan C

PILIHAN 1:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

PILIHAN 2:

[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] forCellReuseIdentifier:@"cell"];

dalam kode di atas nibWithNibName:@"CustomCell"berikan nama nib Anda alih-alih nama nib saya CustomCell

CEPAT

PILIHAN 1:

tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

PILIHAN 2:

tableView.registerNib(UINib(nibName: "NameInput", bundle: nil), forCellReuseIdentifier: "Cell") 

dalam kode di atas nibName:"NameInput"beri nama nib Anda

pengguna3182143
sumber
3

Bekerja dengan Swift 3.0:

override func viewDidLoad() {
super.viewDidLoad()

self.myList.register(UINib(nibName: "MyTableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
}



public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myList.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as! MyTableViewCell

return cell
}
norbDEV
sumber
2

Saya menghabiskan berjam-jam semalam untuk mencari tahu mengapa tabel yang saya buat secara program crash pada [myTable setDataSource: self]; Tidak apa-apa berkomentar dan memunculkan meja kosong, tetapi jatuh setiap kali saya mencoba untuk mencapai sumber data;

Saya memiliki delegasi yang diatur dalam file h: @interface myViewController: UIViewController

Saya memiliki kode sumber data dalam implementasi saya dan masih BOOM !, macet setiap waktu! TERIMA KASIH untuk "xxd" (nr 9): menambahkan bahwa baris kode menyelesaikannya untuk saya! Sebenarnya saya meluncurkan tabel dari tombol IBAction, jadi inilah kode lengkap saya:

    - (IBAction)tapButton:(id)sender {

    UIViewController* popoverContent = [[UIViewController alloc]init];

    UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
    popoverView.backgroundColor = [UIColor greenColor];
    popoverContent.view = popoverView;

    //Add the table
    UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)         style:UITableViewStylePlain];

   // NEXT THE LINE THAT SAVED MY SANITY Without it the program built OK, but crashed when      tapping the button!

    [table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    table.delegate=self;
    [table setDataSource:self];
    [popoverView addSubview:table];
    popoverContent.contentSizeForViewInPopover =
    CGSizeMake(200, 300);

    //create a popover controller
    popoverController3 = [[UIPopoverController alloc]
                          initWithContentViewController:popoverContent];
    CGRect popRect = CGRectMake(self.tapButton.frame.origin.x,
                                self.tapButton.frame.origin.y,
                                self.tapButton.frame.size.width,
                                self.tapButton.frame.size.height);


    [popoverController3 presentPopoverFromRect:popRect inView:self.view   permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];



   }


   #Table view data source in same m file

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
   {
    NSLog(@"Sections in table");
    // Return the number of sections.
    return 1;
   }

   - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
  {
    NSLog(@"Rows in table");

    // Return the number of rows in the section.
    return myArray.count;
   }

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath    *)indexPath
    {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSString *myValue;

    //This is just some test array I created:
    myValue=[myArray objectAtIndex:indexPath.row];

    cell.textLabel.text=myValue;
    UIFont *myFont = [ UIFont fontWithName: @"Arial" size: 12.0 ];
    cell.textLabel.font  = myFont;

    return cell;
   }

Ngomong-ngomong: tombol harus dihubungkan dengan sebagai IBAction dan sebagai IBOutlet jika Anda ingin melabuhkan popover ke sana.

UIPopoverController * popoverController3 dideklarasikan dalam file H langsung setelah @interface antara {}

Simone
sumber
2

FWIW, saya mendapatkan kesalahan yang sama ketika saya lupa mengatur pengidentifikasi sel di storyboard. Jika ini adalah masalah Anda, maka di papan cerita klik sel tampilan tabel dan setel pengidentifikasi sel di editor atribut. Pastikan pengidentifikasi sel yang Anda atur di sini sama dengan

static NSString *CellIdentifier = @"YourCellIdenifier";
klakson
sumber
2

Saya memiliki masalah yang sama, mengalami kesalahan yang sama dan bagi saya itu berfungsi seperti ini:

[self.tableView registerNib:[UINib nibWithNibName:CELL_NIB_HERE bundle: nil] forCellReuseIdentifier:CELL_IDENTIFIER_HERE];

Mungkin itu akan bermanfaat bagi orang lain.

CarmenA
sumber
2

Saya mengatur semuanya dengan benar di Storyboard dan melakukan build bersih tetapi terus mendapatkan kesalahan " harus mendaftarkan nib atau kelas untuk pengidentifikasi atau menghubungkan sel prototipe di storyboard "

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Memperbaiki kesalahan tapi saya masih bingung. Saya tidak menggunakan 'sel khusus', hanya tampilan dengan tampilan tabel yang diembed. Saya telah mendeklarasikan viewcontroller sebagai delegasi dan sumber data dan memastikan pengidentifikasi sel cocok dalam file. apa yang terjadi di sini?

FrostyL
sumber
1

Ini mungkin tampak bodoh bagi sebagian orang tetapi itu membuat saya. Saya mendapatkan kesalahan ini dan masalahnya bagi saya adalah saya mencoba menggunakan sel statis tetapi kemudian secara dinamis menambahkan lebih banyak barang. Jika Anda memanggil metode ini sel Anda harus prototipe dinamis. Pilih sel di storyboard dan di bawah inspektur Atribut, hal pertama mengatakan 'Konten' dan Anda harus memilih prototipe dinamis bukan statis.

Chase Roberts
sumber
TERIMA KASIH! Ini persis masalah saya.
Isaiah Turner
1

Hanya pelengkap jawaban: Mungkin ada saatnya Anda mengatur semuanya dengan benar, tetapi Anda mungkin secara tidak sengaja menambahkan beberapa UI lain di dalam Anda .xib , seperti UIButton: masukkan deskripsi gambar di sini Hapus saja UI tambahan, itu berfungsi.

DrustZ
sumber
1

Pastikan CellIdentifier == pengidentifikasi sel di storyboard, kedua nama sama. Semoga ini berhasil untuk Anda

Ankit garg
sumber
0

Dalam kasus saya, kecelakaan itu terjadi ketika saya menelepondeselectRowAtIndexPath:

Garis itu [tableView deselectRowAtIndexPath:indexPath animated:YES];

Mengubahnya menjadi [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; TETAP MASALAH SAYA!

Semoga ini bisa membantu siapa saja

Offek
sumber
0

Di Swift masalah ini dapat diselesaikan dengan menambahkan kode berikut di

viewDidLoad

metode.

tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "your_reuse_identifier")
arango_86
sumber
-1

Mengalami kesalahan ini, bc penggunaan ulang pengenal sel salah - kesalahan pemula tetapi itu terjadi: 1. Membuat PASTI penggunaan kembali idenifier sel tidak memiliki kesalahan ejaan atau huruf yang hilang. 2. Sejalan dengan itu, jangan lupa jumlah kapitalisasi. 3. Nol bukan "O" (Ohs)

John Pitts
sumber