2010-08-23 33 views
32

Khi táo phát triển UITableView cho iPhone đầu tiên, chúng có vấn đề về hiệu suất khi cuộn qua nó. Sau đó, một kỹ sư thông minh phát hiện ra rằng nguyên nhân của việc này là phân bổ các vật thể đi kèm với một mức giá, do đó, ông đã đưa ra một cách để tái sử dụng các tế bào.UITableView dequeueReusableCellWithIdentifier Lý thuyết

"phân bổ đối tượng có chi phí hiệu quả, đặc biệt nếu việc phân bổ có thể xảy ra nhiều lần trong khoảng thời gian-nói ngắn, khi cuộn người dùng một cái nhìn bảng. Nếu bạn sử dụng lại các tế bào thay vì phân bổ mới, bạn tăng cường hiệu suất xem bảng. "

Nguồn: Thư viện tham khảo iOS

Để tái sử dụng một tế bào bạn sử dụng:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

Bây giờ, những gì tôi đang tự hỏi là, những gì thực sự xảy ra ở đây? Liệu nó nhìn trong TableView nếu có một tế bào với định danh đó và chỉ trả về một trong đó? Vâng yea duh, nhưng nếu nó gửi một tham chiếu thay vì phân bổ và tôi có một cái nhìn bảng với giả sử 4 ô với cùng một định danh tất cả có thể nhìn thấy. Làm thế nào nó có thể nhân bản thân thành bốn trường hợp mà không phân bổ?

Tôi muốn biết điều này vì tôi đang xây dựng thành phần kiểu lịch và tất cả các ô có cùng cấu trúc chỉ văn bản trong các thay đổi. Vì vậy, nếu tôi bằng cách nào đó có thể tái sử dụng các tế bào của tôi thay vì phân bổ tôi nghĩ rằng tôi có thể có được một hiệu suất tốt hơn.

Lý thuyết của riêng tôi là nó phân bổ bốn ô (đơn giản là vì nó có quá). Khi một tế bào biến mất khỏi màn hình, nó sẽ được đưa vào hàng đợi sử dụng lại của TableView. Khi một tế bào mới là cần thiết nó trông trong que nếu một tế bào với cùng một định danh có sẵn, nó gọi phương thức prepareForReuse trên ô đó và nó tự xóa khỏi hàng đợi.

+0

Câu trả lời ngắn gọn: Có. Nó có một hàng đợi tái sử dụng riêng biệt/thiết lập mà không giống như những thứ đã có trong bảng. –

Trả lời

43

dequeueReusableCellWithIdentifier: chỉ trả lại cell nếu nó đã được đánh dấu là sẵn sàng để sử dụng lại. Đây là lý do tại sao trong hầu hết các phương pháp cellForRowAtIndexPath: bạn sẽ thấy một cái gì đó giống như

 


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

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

// Do something to cell 

return cell; 
 

Trong thực tế, đủ hàng sẽ được phân bổ để điền vào phần nhìn thấy được của tableview (cộng với một hoặc hai hơn). Khi cells scroll tắt màn hình, chúng sẽ bị xóa khỏi table và được đánh dấu là sẵn sàng cho reuse. Khi hàng đợi của "ô sẵn có" phát triển, dòng yêu cầu dequeued cell của bạn sẽ bắt đầu có được cell để sử dụng, tại thời điểm đó bạn sẽ không phải phân bổ nữa.

+3

Phần 'một hoặc hai phần' không chính xác. Nó được phân bổ * chính xác * những gì cần thiết. Hãy thử điều này và bạn sẽ thấy. –

+0

Thực ra như St3fan nói nếu bạn NSLog phương thức mà nó yêu cầu một ô bạn sẽ thấy nó chỉ yêu cầu ô cần thiết. – Mark

+2

Tôi có thể hơi vội vàng theo cách tôi giải thích điều đó. "Điều cần thiết" thay đổi tùy theo hoàn cảnh. Khi bạn bắt đầu cuộn UITableView, nhiều yếu tố sẽ được phát. Một ví dụ: nếu bạn cuộn một khung nhìn bảng dài rất nhanh, có thể khiến bảng yêu cầu một ô khi không có sẵn để khử. –

13

Mã cho deqeueueReusableCellsWithIdentifier: sẽ giống như thế này:

(Trích từ một trong những dự án của riêng tôi, nơi tôi làm điều gì đó tương tự với views/trang trong một cái nhìn cuộn paged)

- (UIView*) dequeueReusablePage 
{ 
    UIView* page = [reusablePages_ anyObject]; 
    if (page != nil) { 
     [[page retain] autorelease]; 
     [reusablePages_ removeObject: page]; 
    } 
    return page; 
} 

Vì vậy, nó giữ một đơn giản NSMutableSet với các đối tượng tái sử dụng.

Khi các ô cuộn ra khỏi màn hình và không còn hiển thị, chúng được đặt trong bộ này.

Vì vậy, bạn bắt đầu với bộ trống và bộ này sẽ chỉ phát triển nếu bạn thực sự có nhiều dữ liệu hơn để hiển thị thì hiển thị trên màn hình.

Đã sử dụng cuộn di động ở phía trên cùng của màn hình, được đặt trong bộ, sau đó được lấy cho ô xuất hiện ở cuối màn hình.

2

Mục đích của dequeueReusableCellWithIdentifier là sử dụng ít bộ nhớ hơn. nếu chúng ta sử dụng 100 ô trong một tableView thì cần phải tạo 100 ô mỗi lần. Nó làm giảm chức năng ứng dụng và có thể gây ra sự cố. Để cho rằng dequeueReusableCellWithIdentifier khởi tạo số lượng ô cụ thể mà chúng tôi đã tạo và các ô sẽ sử dụng lại để xử lý tiếp.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *TableIdentifier = @"YourCellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier]; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier]; 
    } 

    ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init]; 
    myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row]; 
    myCell.MyCellImage.backgroundColor = [UIColor blueColor]; 

    return cell; 
} 
Các vấn đề liên quan