2012-07-07 14 views
5

Tôi muốn sử dụng các cuộc gọi chuyển động hàng thuận tiện của iOS 5 để tạo hoạt ảnh cho một số lần thay đổi trạng thái mô hình, thay vì xóa theo kiểu cũ hơn chèn.UITableView: sử dụng moveRowAtIndexPath: toIndexPath: và reloadRowsAtIndexPaths: withRowAnimation: cùng xuất hiện bị hỏng

Thay đổi có thể bao gồm cả cập nhật sắp xếp lại và tại chỗ và tôi muốn tạo hiệu ứng cho cả hai, vì vậy một số hàng sẽ cần reloadRowsAtIndexPaths.

Nhưng! UITableView dường như chỉ đơn giản là sai trong việc xử lý tải lại hàng trong sự hiện diện của di chuyển, nếu ô được cập nhật thay đổi vị trí do di chuyển. Sử dụng lệnh xóa + chèn cũ hơn, theo cách tương đương, hoạt động tốt.

Dưới đây là một số mã; Tôi xin lỗi vì sự rách rưới nhưng nó biên dịch và chạy. Thịt nằm trong phương pháp doMoves:. Triển lãm bên dưới.

#define THISWORKS 

@implementation ScrambledList // extends UITableViewController 
{ 
    NSMutableArray *model; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    model = [NSMutableArray arrayWithObjects: 
      @"zero", 
      @"one", 
      @"two", 
      @"three", 
      @"four", 
      nil]; 
    [self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle: 
#ifdef THISWORKS 
               @"\U0001F603" 
#else 
               @"\U0001F4A9" 
#endif 
                       style:UIBarButtonItemStylePlain 
                      target:self 
                      action:@selector(doMoves:)]]; 
} 

-(IBAction)doMoves:(id)sender 
{ 
    int fromrow = 4, torow = 0, changedrow = 2; // 2 = its "before" position, just like the docs say. 

    // some model changes happen... 
    [model replaceObjectAtIndex:changedrow 
        withObject:[[model objectAtIndex:changedrow] stringByAppendingString:@"\u2032"]]; 
    id tmp = [model objectAtIndex:fromrow]; 
    [model removeObjectAtIndex:fromrow]; 
    [model insertObject:tmp atIndex:torow]; 

    // then we tell the table view what they were 
    [self.tableView beginUpdates]; 
    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:changedrow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationRight]; // again, index for the "before" state; the tableview should figure out it really wants row 3 when the time comes 
#ifdef THISWORKS 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:fromrow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationAutomatic]; 
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:torow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationAutomatic]; 
#else // but this doesn't 
    [self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:fromrow inSection:0] 
         toIndexPath:[NSIndexPath indexPathForRow:torow inSection:0]]; 
#endif 
    [self.tableView endUpdates]; 
} 

#pragma mark - Table view data source boilerplate, not very interesting 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return model.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@""]; 
    if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@""]; 
    [cell.textLabel setText:[[model objectAtIndex:indexPath.row] description]]; 
    [cell.detailTextLabel setText:[NSString stringWithFormat:@"this cell was provided for row %d", indexPath.row]]; 
    return cell; 
} 

Mã nào: thiết lập một mô hình nhỏ (mảng có thể thay đổi nhỏ); khi một nút được đẩy, nó sẽ tạo ra một thay đổi nhỏ cho phần tử ở giữa của danh sách và di chuyển phần tử cuối cùng thành phần tử đầu tiên. Sau đó, nó cập nhật chế độ xem bảng để phản ánh những thay đổi này: tải lại hàng ở giữa, xóa hàng cuối cùng và chèn một hàng mới bằng 0.

Tác phẩm này. Trong thực tế, việc thêm ghi nhật ký vào cellForRowAtIndexPath cho thấy rằng mặc dù tôi yêu cầu tải lại hàng 2, bảng xem chính xác yêu cầu hàng 3 vì chèn một khi đã đến lúc thực sự cập nhật. Huzzah!

Bây giờ, hãy nhận xét #ifdef đầu để sử dụng lệnh moveRowAtIndexPath thay thế.

Bây giờ tableview loại bỏ dòng 2, yêu cầu cho một hàng tươi (sai!), Và chèn nó ở hàng-2 vị trí cuối cùng (cũng sai!). Kết quả thực là hàng 1 đã di chuyển xuống hai vị trí thay vì một và cuộn màn hình ngoài để buộc tải lại cho biết cách nó không đồng bộ với mô hình. Tôi có thể hiểu nếu moveRowAtIndexPath thay đổi mô hình riêng của tableview theo thứ tự khác, yêu cầu sử dụng "mới" thay vì đường dẫn chỉ mục "cũ" trong tải lại hoặc tìm nạp mô hình, nhưng đó không phải là những gì đang diễn ra. Lưu ý rằng trong pic "sau" thứ hai, hàng thứ ba và thứ tư theo thứ tự ngược lại, không nên xảy ra bất kể ô nào tôi đang tải lại.

before state

after one button push, delete-insert style

after one button push, move-style

từ vựng của tôi đã phát triển rực rỡ nguyền rủa Apple. Tôi có nên nguyền rủa bản thân mình không? Hàng di chuyển chỉ đơn giản không tương thích với tải lại hàng trong cùng khối cập nhật (cũng như, tôi nghi ngờ, chèn và xóa)? Bất cứ ai có thể khai sáng cho tôi trước khi tôi gửi báo cáo lỗi?

+0

Rất thú vị! –

+0

Bạn đã bao giờ tìm thấy một giải pháp cho điều này? Tôi đang chạy vào cùng một vấn đề chính xác. –

+0

Không! Tôi đã gửi một báo cáo lỗi đã bị đóng với "không đủ thông tin" và yêu cầu kiểm tra nó theo ios6 (mà tôi chưa nhận được, nhưng nếu bạn gặp sự cố thì có thể nó không cố định và UICollectionView có thể tương tự vấn đề.) Hai cách giải quyết tôi mong đợi để làm việc là: làm hai riêng biệt bắt đầu/endUpdates khối, một cho tải lại sau đó một cho di chuyển/chèn/xóa; hoặc bỏ qua reloadRowsAtIndexPaths hoàn toàn và định vị/phục hồi lại các ô thích hợp bằng tay. – rgeorge

Trả lời

3

Tôi vừa dành chút thời gian chơi với mã của bạn và tôi đồng ý; có vẻ như nó không hoạt động.

Toàn bộ khu vực này hơi bị ghi lại một chút nhưng không thực sự nói rằng bạn có thể trộn moveRowAtIndexPath:toIndexPath: với các phương thức tải lại. Nó hiện nói ở chỗ nó có thể được trộn lẫn với phương pháp chèn hàng và xóa hàng. Những người này dường như làm việc nếu tôi sửa đổi mã của bạn để thực hiện những thay thế. Vì vậy, bạn có thể yêu cầu tăng cường, chứ không phải nộp lỗi. Dù bằng cách nào, tôi chắc chắn sẽ gửi nó đến radar.

+0

Cảm ơn bạn đã xác nhận. Radar đã được gửi đi. Nếu Apple đã từng giải quyết nó, tôi sẽ nối thêm độ phân giải. – rgeorge