Có thể làm mới một UITableViewCell trong UITableView không?


182

Tôi có một tùy chỉnh UITableViewsử dụng UITableViewCells. Mỗi cái UITableViewCellcó 2 nút. Nhấp vào các nút này sẽ thay đổi hình ảnh trong một UIImageViewô.

Có thể làm mới từng ô riêng biệt để hiển thị hình ảnh mới? Bất kỳ trợ giúp được đánh giá cao.

Câu trả lời:


323

Khi bạn có indexPath của ô của mình, bạn có thể làm một cái gì đó như:

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

Trong Xcode 4.6 trở lên:

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

Tất nhiên, bạn có thể đặt bất cứ thứ gì bạn thích làm hiệu ứng hoạt hình.


4
Nitpicking ở đây, nhưng tất nhiên nếu bạn chỉ làm mới một ô duy nhất bạn có thể muốn sử dụng [NSArray arrayWithObject:]thay thế.
Leo Cassarani

57
Ngoài ra, trong tình huống này, beginUpdatesendUpdateskhông cần thiết.
kubi

2
OP không hoạt hình bất cứ điều gì, vì vậy không cần phải gọi bắt đầu / kết thúc
kubi

2
Miễn là phương thức không nói không được dùng trong phiên bản Xcode công khai cuối cùng, tất cả các phiên bản iOS sẽ ổn.
Alejandro Iván

1
@Supertecnoboff đúng, nhưng đến một lúc nào đó nó có thể được thay thế hoặc sẽ thay đổi hành vi của nó. Tốt hơn hết là xử lý sự mất giá càng sớm càng tốt
Alejandro Iván

34

Tôi đã cố gắng chỉ gọi -[UITableView cellForRowAtIndexPath:], nhưng không được. Nhưng, những công việc sau đây đối với tôi chẳng hạn. Tôi allocreleasecác NSArrayquản lý bộ nhớ chặt chẽ.

- (void)reloadRow0Section0 {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    [indexPaths release];
}

Là [phát hành indexPaths] cần thiết ở đây? Tôi nghĩ bạn chỉ cần điều đó nếu bạn tự phân bổ đối tượng.
powerj1984

4
Ông đã phân bổ mảng indexPaths. Nhưng câu hỏi tốt hơn là tại sao anh ta nghĩ rằng "quản lý bộ nhớ chặt chẽ" là cần thiết. Autorelease sẽ làm công việc hoàn hảo ở đây.
John Cromartie

22

Nhanh:

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

    tableView.beginUpdates()
    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
    tableView.endUpdates()
}

Gọi phương pháp này ở đâu?
Master AgentX

18

reloadRowsAtIndexPaths:vẫn ổn, nhưng vẫn sẽ buộc UITableViewDelegatecác phương pháp bắn.

Cách tiếp cận đơn giản nhất tôi có thể tưởng tượng là:

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

Điều quan trọng là phải configureCell:thực hiện triển khai của bạn trên luồng chính, vì nó không hoạt động trên luồng không phải UI (cùng câu chuyện với reloadData/ reloadRowsAtIndexPaths:). Đôi khi nó có thể hữu ích để thêm:

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

Cũng đáng để tránh công việc sẽ được thực hiện bên ngoài chế độ xem hiện tại:

BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
if (cellIsVisible)
{
    ....
}

Tại sao bạn không muốn đại biểu được gọi?
kernix

Đây là cách tiếp cận tốt nhất vì nó không bắt buộc chế độ xem bảng di chuyển từ trên xuống so với phương thức reloadRowsAtIndexPaths: hoặc reloadData.
ZviBar

Tôi đã làm điều này và cuối cùng bị bắt bởi thực tế là tế bào đã được tái chế
Travelling Man

16

Nếu bạn đang sử dụng TableViewCells tùy chỉnh, chung chung

[self.tableView reloadData];    

không trả lời hiệu quả câu hỏi này trừ khi bạn rời khỏi chế độ xem hiện tại và quay lại. Không có câu trả lời đầu tiên.

Để tải lại thành công ô xem bảng đầu tiên của bạn mà không chuyển đổi chế độ xem , hãy sử dụng mã sau:

//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];
}

Chèn phương thức làm mới sau đây gọi đến phương thức trên để bạn có thể tùy chỉnh chỉ tải lại ô trên cùng (hoặc toàn bộ chế độ xem bảng nếu bạn muốn):

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

    //finish refreshing 
    [refreshControl endRefreshing];
}

Bây giờ bạn đã sắp xếp nó, bên trong bạn viewDidLoadthêm vào như sau:

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

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

[self.tableView addSubview:refreshControl];

Bây giờ bạn có một tính năng bảng làm mới tùy chỉnh sẽ tải lại ô trên cùng. Để tải lại toàn bộ bảng, thêm

[self.tableView reloadData]; để phương pháp làm mới mới của bạn.

Nếu bạn muốn tải lại dữ liệu mỗi khi bạn chuyển chế độ xem, hãy triển khai phương thức:

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

6

Swift 3:

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

4

Chỉ cần cập nhật các câu trả lời này một chút với cú pháp bằng chữ mới trong iOS 6 - bạn có thể sử dụng Paths = @ [indexPath] cho một đối tượng hoặc Paths = @ [indexPath1, indexPath2, ...] cho nhiều đối tượng.

Cá nhân, tôi đã tìm thấy cú pháp theo nghĩa đen cho các mảng và từ điển là vô cùng hữu ích và tiết kiệm thời gian lớn. Nó chỉ dễ đọc hơn, vì một điều. Và nó loại bỏ sự cần thiết của một con số không ở cuối danh sách đa đối tượng, vốn luôn là một lỗi cá nhân. Tất cả chúng ta đều có cối xay gió để nghiêng, vâng? ;-)

Chỉ cần nghĩ rằng tôi sẽ ném nó vào hỗn hợp. Hy vọng nó giúp.


Nói Greg, thực sự là một ví dụ về cú pháp đó, làm ơn? Cảm ơn!
Fattie

3

Đây là tiện ích mở rộng UITableView với 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()
    }

}

Gọi với

self.tableView.updateRow(row: 1)

0

Tôi cần tế bào nâng cấp nhưng tôi muốn đóng bàn phím. Nếu tôi sử dụng

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

bàn phím biến mất

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.