Apakah mungkin untuk me-refresh satu UITableViewCell dalam UITableView?

182

Saya punya kebiasaan UITableViewmenggunakan UITableViewCells. Masing-masing UITableViewCellmemiliki 2 tombol. Mengklik tombol-tombol ini akan mengubah gambar di UIImageViewdalam sel.

Apakah mungkin untuk menyegarkan setiap sel secara terpisah untuk menampilkan gambar baru? Bantuan apa pun dihargai.

Wisaya iOS
sumber

Jawaban:

323

Setelah Anda memiliki indexPath sel Anda, Anda dapat melakukan sesuatu seperti:

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; 

Dalam Xcode 4.6 dan lebih tinggi:

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; 

Anda dapat mengatur apa pun yang Anda suka sebagai efek animasi, tentu saja.

Romain
sumber
4
Nitpicking di sini, tetapi tentu saja jika Anda hanya menyegarkan satu sel, Anda mungkin ingin menggunakannya [NSArray arrayWithObject:].
Leo Cassarani
57
Juga, dalam situasi ini, beginUpdatesdan endUpdatestidak perlu.
kubi
2
OP tidak menjiwai apa pun, jadi tidak perlu memanggil awal / akhir
kubi
2
Selama metode ini tidak mengatakan usang dalam versi Xcode publik terakhir, semua versi iOS harus baik-baik saja.
Alejandro Iván
1
@Supertecnoboff benar, tetapi pada titik tertentu dapat diganti atau akan mengubah perilakunya. Lebih baik menangani penghentian sesegera mungkin
Alejandro Iván
34

Saya mencoba menelepon -[UITableView cellForRowAtIndexPath:], tetapi itu tidak berhasil. Tapi, berikut ini berfungsi untuk saya misalnya. Aku allocdan releaseyang NSArrayuntuk manajemen memori yang ketat.

- (void)reloadRow0Section0 {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    [indexPaths release];
}
ma11hew28
sumber
Apakah [rilis indexPaths] perlu di sini? Saya pikir Anda hanya perlu itu jika Anda mengalokasikan objek sendiri.
powerj1984
4
Dia memang mengalokasikan array indexPaths. Tetapi pertanyaan yang lebih baik adalah mengapa ia berpikir "manajemen memori ketat" diperlukan. Autorelease akan melakukan pekerjaan dengan sangat baik di sini.
John Cromartie
22

Cepat:

func updateCell(path:Int){
    let indexPath = NSIndexPath(forRow: path, inSection: 1)

    tableView.beginUpdates()
    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
    tableView.endUpdates()
}
Esqarrouth
sumber
Di mana harus memanggil metode ini?
Master AgentX
18

reloadRowsAtIndexPaths:baik-baik saja, tetapi masih akan memaksa UITableViewDelegatemetode untuk menembak.

Pendekatan paling sederhana yang dapat saya bayangkan adalah:

UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configureCell:cell forIndexPath:indexPath];

Ini penting untuk memohon Anda configureCell:pelaksanaan pada thread utama, karena itu tidak akan berhasil di thread non-UI (cerita yang sama dengan reloadData/ reloadRowsAtIndexPaths:). Terkadang mungkin bermanfaat untuk menambahkan:

dispatch_async(dispatch_get_main_queue(), ^
{
    [self configureCell:cell forIndexPath:indexPath];
});

Layak juga untuk menghindari pekerjaan yang akan dilakukan di luar tampilan yang saat ini terlihat:

BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
if (cellIsVisible)
{
    ....
}
Maciek Czarnik
sumber
Mengapa Anda tidak ingin delegasi dipanggil?
kernix
Ini adalah pendekatan terbaik karena tidak memaksa tampilan tabel untuk menggulir semua jalan ke atas yang bertentangan dengan reloadRowsAtIndexPaths: atau metode reloadData.
ZviBar
Saya melakukan ini dan akhirnya tertangkap oleh fakta bahwa sel itu didaur ulang
Travelling Man
16

Jika Anda menggunakan TableViewCells khusus, generik

[self.tableView reloadData];    

tidak secara efektif menjawab pertanyaan ini kecuali Anda meninggalkan tampilan saat ini dan kembali. Tidak juga jawaban pertama.

Untuk berhasil memuat ulang sel tampilan tabel pertama Anda tanpa beralih tampilan , gunakan kode berikut:

//For iOS 5 and later
- (void)reloadTopCell {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
}

Masukkan metode penyegaran berikut yang memanggil metode di atas sehingga Anda dapat memuat ulang hanya sel atas (atau seluruh tampilan tabel jika diinginkan):

- (void)refresh:(UIRefreshControl *)refreshControl {
    //call to the method which will perform the function
    [self reloadTopCell];

    //finish refreshing 
    [refreshControl endRefreshing];
}

Sekarang Anda memiliki yang diurutkan, di dalam Anda viewDidLoadtambahkan yang berikut:

//refresh table view
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];

[refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];

[self.tableView addSubview:refreshControl];

Anda sekarang memiliki fitur tabel penyegaran khusus yang akan memuat ulang sel atas. Untuk memuat ulang seluruh tabel, tambahkan

[self.tableView reloadData]; ke metode penyegaran baru Anda.

Jika Anda ingin memuat ulang data setiap kali Anda beralih tampilan, terapkan metode ini:

//ensure that it reloads the table view data when switching to this view
- (void) viewWillAppear:(BOOL)animated {
    [self.tableView reloadData];
}
App Dev Guy
sumber
6

Swift 3:

tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
ergunkocak
sumber
4

Hanya untuk memperbarui jawaban ini sedikit dengan sintaks literal baru di iOS 6 - Anda dapat menggunakan Paths = @ [indexPath] untuk objek tunggal, atau Paths = @ [indexPath1, indexPath2, ...] untuk beberapa objek.

Secara pribadi, saya telah menemukan sintaks literal untuk array dan kamus sangat bermanfaat dan menghemat waktu. Hanya saja lebih mudah dibaca, untuk satu hal. Dan itu menghilangkan kebutuhan untuk nol di akhir daftar multi-objek, yang selalu menjadi bugaboo pribadi. Kita semua punya kincir angin untuk dimiringkan, ya? ;-)

Hanya berpikir saya akan membuang ini ke dalam campuran. Semoga ini bisa membantu.

Gregory Hill
sumber
Katakanlah Greg, apa sebenarnya contoh dari sintaks itu di sana? Terima kasih!
Fattie
3

Berikut ini adalah ekstensi UITableView dengan Swift 5:

import UIKit

extension UITableView
{    
    func updateRow(row: Int, section: Int = 0)
    {
        let indexPath = IndexPath(row: row, section: section)

        self.beginUpdates()
        self.reloadRows(at: [indexPath as IndexPath], with: UITableView.RowAnimation.automatic)
        self.endUpdates()
    }

}

Telepon dengan

self.tableView.updateRow(row: 1)
iphaaw
sumber
0

Saya perlu sel upgrade tetapi saya ingin menutup keyboard. Jika saya gunakan

let indexPath = NSIndexPath(forRow: path, inSection: 1)
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
tableView.endUpdates()

keyboard menghilang


sumber