2013-06-07 34 views
5

Tôi đang sử dụng lại tiêu đề, giữ chúng trong từ điển trong đó số phần là khóa và chế độ xem tiêu đề là giá trị.Khung hình của chế độ xem tiêu đề đã thay đổi vĩnh viễn sau khi xóa phần UITableView của

Sau khi tôi đã xóa hoạt ảnh một phần và tải lại một phần khác, chế độ xem tiêu đề của chỉ những phần này "biến mất". Sau khi tìm kiếm một số, tôi thấy rằng khung của chế độ xem tiêu đề đã được thay đổi. Frame.X chế độ xem tiêu đề từ phần đã bị xóa với UITableViewRowAnimationRight shifter sang phải theo chiều rộng màn hình (320) và hình đã được tải lại với UITableViewRowAnimationAutomatic được chuyển bởi Y.

Vấn đề chính và sự nhầm lẫn xuất phát từ thực tế là tôi không thể thay đổi các khung này! Vâng, họ thay đổi lúc đầu, nhưng không có gì thay đổi trực quan và trên các cuộc gọi khác của viewForHeaderInSection: khung hình được chuyển một lần nữa.

Sau đây là cách tôi làm điều đó:

Giả sử chúng ta có 3 phần, với dữ liệu của mỗi đặt tại một trong những mảng _first, _second_third. Và bằng nút bấm của touchupinside chúng tôi gọi handleTouchUp:. (_second vẫn không thay đổi)

- (void) handleTouchUp: (UIButton *)sender 
{ 
    if ([_first count] == 0) { 
     sectionCount = 3; 
     _first = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", nil]; 
     _third = [NSMutableArray arrayWithObjects: @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil]; 
     [tableView reloadData]; 
    } else { 
     sectionCount = 2; 
     [_first removeAllObjects]; 
     _third = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", @"Third 1", @"Third 2", 
                @"Third 3", @"Third 4", @"Third 5", nil]; 
     [tableView beginUpdates]; 
     [tableView deleteSections: [NSIndexSet indexSetWithIndex: 0] withRowAnimation:UITableViewRowAnimationRight]; 
     [tableView reloadSections: [NSIndexSet indexSetWithIndex: 2] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     [tableView endUpdates]; 
    } 
} 


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    NSNumber *key = [NSNumber numberWithInteger: section]; 
    UIView *header = [_headers objectForKey: key]; 
    if (header) { 

    } else { 
     header = [[UIView alloc] init]; 
     switch (section) { 
      //Doing something with header here (e.g. set background color) 
     } 
     [_headers setObject:header forKey: key]; 
    } 

    [header setFrame: CGRectMake(0, 0, 320, 25)]; 

    return header; 
} 

Here is full code of ViewController.mtest project

UPDATE: Có thể có một số lỗi khác trong dự án, nhưng nó không quan trọng - đó là dự án thử nghiệm. Vấn đề quan trọng duy nhất là lượt xem tiêu đề không hợp lệ. Việc xóa chế độ xem không hợp lệ và tạo chế độ xem mới không phải là giải pháp - nó sẽ giết chết điểm sử dụng lại lượt xem tiêu đề.

Trả lời

3

Tôi đã tìm thấy một số sai lầm trong dự án của bạn, điều này thực sự dẫn đến một số sự cố và tôi tin rằng chúng cũng chịu trách nhiệm đối với các lỗi xem tiêu đề bạn thấy trong ứng dụng. Sau khi tôi đã sửa các ứng dụng đó và ứng dụng có vẻ hoạt động đúng với tôi.

Dưới đây là một phiên bản cập nhật của dự án của bạn: https://bitbucket.org/reydan/tableheaderviews

tôi đã cố gắng để giữ nó như là tương tự càng tốt để dự án ban đầu của bạn, nhưng tôi đã phải thực hiện một số thay đổi. Nếu bạn tin rằng nó không phù hợp với chức năng mong muốn của bạn, hãy để lại một bình luận và tôi sẽ cập nhật (Đây là những gì tôi suy ra rằng dự án sẽ hoạt động như thế) Mọi thay đổi được giải thích bên dưới, cũng có thể được nhìn thấy trong dự án cập nhật này.

Các vấn đề tôi đã tìm thấy có liên quan đến thực tế là nếu bạn xóa một phần khỏi chế độ xem bảng, tất cả phần sau khi chỉ mục sẽ thay đổi (với -1). Điều này là bình thường, vì chỉ mục phần thực sự là một chỉ mục chứ không phải là một khóa duy nhất được gán cho từng phần.

Sau khi bạn loại bỏ phần đầu tiên, phần thứ ba bây giờ đã có chỉ mục = 1 và bảng xem phương thức đại biểu đọc dữ liệu không chính xác (bao gồm cả khung nhìn tiêu đề) vì bạn có mọi thứ dựa trên chỉ mục phần.

Để khắc phục điều này, tôi đã thay đổi bộ nhớ cache chế độ xem tiêu đề để sử dụng mảng dữ liệu làm khóa (_first, _second hoặc _third). Để thực hiện dễ dàng hơn này, tôi đã tạo ra một phương pháp có thể được gọi là từ nhiều nơi và trả về mảng dữ liệu chính xác dựa trên các chỉ số phần và phần hiện đếm:

- (NSArray*)dataArrayForSection:(NSInteger)section 
{ 
    if (sectionCount == 3) 
    { 
     switch (section) 
     { 
      case 0: return _first; 
      case 1: return _second; 
      case 2: return _third; 
     } 
    } 
    else 
    { 
     switch (section) 
     { 
      case 0: return _second; 
      case 1: return _third; 
     } 
    } 

    return nil; 
} 

Bây giờ bộ nhớ cache tiêu đề sử dụng các mảng dữ liệu như các phím , điều quan trọng là phải loại bỏ các mục tiêu đề khi phân bổ lại các mảng trong phương thức handleTouchUp.

- (void) handleTouchUp: (UIButton *)sender 
{ 
    NSLog(@"Touched!"); 
    if ([_first count] == 0) 
    { 
     sectionCount = 3; 

     // **INSERTED** Removes the cache for the _first and _third keys because you are recreating the arrays again, 
     // and so you are losing the initial key. Not doing this, results in a memory leak 
     [_headers removeObjectForKey:_first]; 
     [_headers removeObjectForKey:_third]; 

     _first = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", nil]; 
     _third = [NSMutableArray arrayWithObjects: @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil]; 

     [tableView reloadData]; 
//  [tableView beginUpdates]; 
//  [tableView reloadSections: [NSIndexSet indexSetWithIndex: 0] withRowAnimation:UITableViewRowAnimationRight]; 
//  [tableView reloadSections: [NSIndexSet indexSetWithIndex: 2] withRowAnimation:UITableViewRowAnimationAutomatic]; 
//  [tableView endUpdates]; 
    } 
    else 

Một điều khác mà tôi cải thiện đang sử dụng lại các ô xem bảng. Bạn nên luôn luôn cố gắng và tái sử dụng UITableViewCells hiện tại (với vài ngoại lệ). cellForRowAtIndexPath giờ giống như sau:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSArray* dataarray = [self dataArrayForSection:indexPath.section]; 


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"my_text_cell"]; 
    if (cell == nil) 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"my_text_cell"]; 


    if (dataarray == nil) 
     cell.textLabel.text = @"default"; 
    else 
     cell.textLabel.text = [dataarray objectAtIndex:indexPath.row]; 


    return cell; 
} 

Nếu bạn có bất kỳ câu hỏi nào, vui lòng để lại nhận xét.

EDIT

tôi đã cố gắng để cập nhật dự án thử nghiệm của tôi như bạn yêu cầu, để giữ cho bộ nhớ cache còn nguyên vẹn và tôi đã thực sự có khả năng tái tạo các lỗi - sau khi xóa tải lại hình ảnh động /, tiêu đề cho phần cuối cùng không nhìn thấy được.

Điều tôi phát hiện ra là hoạt ảnh tải lại tự động iOS chọn là hoạt ảnh mờ dần. Điều này làm cho chế độ xem tiêu đề mờ đi. Tôi đã thử nghiệm điều này bằng cách thêm một nút khác trong ứng dụng đặt alpha = 1 cho tất cả chế độ xem tiêu đề được lưu trong bộ nhớ cache. Sau khi tải lại hình động, tôi nhấn nút này và các khung nhìn tiêu đề xuất hiện chính xác.

Tôi đã thử sử dụng các hoạt ảnh khác, nhưng chúng trông không đẹp.

Cuối cùng, tôi không nghĩ rằng Apple khuyên bạn nên lưu vào chế độ xem tiêu đề bộ nhớ đệm. Trong tài liệu, bắt đầu với iOS 6.0 có một phương pháp mới giải quyết vấn đề này. Nó hoạt động tương tự như tế bào dequeueing, nhưng đối với/footer xem tiêu đề
- (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier

Vì vậy, nếu bạn nhắm mục tiêu iOS 6.0+ sau đó bạn có thể sử dụng thay vì bằng tay bộ nhớ đệm các tiêu đề. Nếu không, giải pháp tôi tìm thấy là xóa khỏi bộ nhớ cache chỉ các khung nhìn tiêu đề cho các phần đã xóa và tải lại (_first và _third).

Tôi đã cập nhật dự án để chỉ xóa tiêu đề phần cuối cùng khi làm mới

+0

Vấn đề là khung của chế độ xem tiêu đề trở nên không hợp lệ sau khi xóa/tải lại hoạt ảnh. Tất cả các lỗi khác (bao gồm cả tái sử dụng các tế bào) không thực sự quan trọng bởi vì nó chỉ là dự án thử nghiệm mà tôi đã viết để hiển thị vấn đề với khung nhìn tiêu đề. Lý do tại sao dự án của bạn không có vấn đề này là bạn luôn tạo lại chế độ xem tiêu đề bị ảnh hưởng bởi hoạt ảnh và không làm điều đó là toàn bộ điểm của chế độ xem tiêu đề "bộ nhớ cache". Ngoài ra tôi đã không nhận được bình luận của bạn về mất phím ban đầu (ngay trước khi loại bỏ tiêu đề từ bộ nhớ cache). – folex

+0

Nhưng dù sao, chế độ xem tiêu đề không được chia nhỏ sau hoạt ảnh, điều đó chỉ là sai. Nếu tôi muốn sử dụng chế độ xem rất giống nhau, tôi sẽ có thể sử dụng chính xác cùng một chế độ xem nếu nó không bị hỏng và nếu chế độ xem đó hiển thị một lần trong cấu trúc phân cấp chế độ xem. Nếu bạn có thể, hãy cố gắng không xóa bộ nhớ cache và bạn sẽ kết thúc với chế độ xem bị hỏng. – folex

+0

Tôi sẽ cố gắng giải thích tốt hơn ý nghĩa của các phím sai. Bạn có chế độ xem tiêu đề được lưu trong bộ nhớ cache cho các khóa 0,1,2. Khi bạn xóa phần đầu tiên (chỉ mục = 0) và làm mới phần 2, làm mới đó sẽ được gọi với chỉ mục = 1 - vì phần đầu tiên biến mất và tất cả các phần khác được dịch chuyển bằng -1. Vì vậy, khi làm mới tiêu đề, dựa trên mã của bạn, bạn sẽ trả lại chế độ xem tiêu đề bằng khóa 1, nhưng uiview chính xác cũng được sử dụng cho phần thứ hai trước đó (phần này không được làm mới và giữ chế độ xem tiêu đề cũ). Có cùng UIView ở 2 nơi mà tôi tin là nguyên nhân gây ra sự cố. –

Các vấn đề liên quan