2012-07-07 3 views
5

iOS 5의 멋진 행 이동 호출을 사용하여 이전 스타일의 delete-and- 끼워 넣다.UITableView : using moveRowAtIndexPath : toIndexPath : andRoadRowsAtIndexPaths : withRowAnimation : 함께 깨진 것처럼 보입니다.

변경 사항에는 순서 변경 및 전체 업데이트가 포함될 수 있으며 둘 다에 애니메이션을 적용하기 때문에 일부 행에는 reloadRowsAtIndexPaths이 필요합니다.

하지만! UITableView은 이동으로 인해 업데이트 된 셀이 위치를 이동하는 경우 행이있을 때 행 재로드를 처리하는 데있어서 명백하게 잘못된 것처럼 보입니다. 이전 delete + insert 호출을 사용하면 동등한 방식으로 정상적으로 작동합니다.

여기에 몇 가지 코드가 있습니다. 나는 자세한 내용을 사과하지만 컴파일하고 실행합니다. 고기는 doMoves: 방법에 있습니다. 아래 박람회.

#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; 
} 

작은 코드 (작은 가변 배열)를 설정합니다. 버튼을 누르면 목록의 중간 요소를 조금 변경하고 마지막 요소를 첫 번째 요소로 이동합니다. 그런 다음 테이블 뷰를 업데이트하여 이러한 변경 사항을 반영합니다. 가운데 행을 다시로드하고 마지막 행을 제거한 다음 새 행 0을 삽입합니다.

이것은 작동합니다. 실제로, cellForRowAtIndexPath에 로깅을 추가하면 행 2를 다시로드하라고 요청하지만 실제로 업데이트를 수행 할 시간이되면 삽입을 위해 행 3을 올바르게 요구합니다. 후자!

대신 moveRowAtIndexPath 호출을 사용하려면 위쪽 #ifdef를 주석 처리하십시오.

는 지금의 tableview 는 새로운 행을 요청 (잘못된!), 2 행을 제거하고, 마지막 행이 위치에 삽입합니다 (또한 잘못된!). 그물 결과는 행 1이 두 개의 슬롯 대신 움직 였고, 화면을 강제로 화면을 벗어나서 강제로 다시 불러 와서 모델과의 동기화 상태가 어떻게 벗어 났는지 보여줍니다. moveRowAtIndexPath이 reload 나 모델 가져 오기에서 "old"인덱스 경로 대신 "new"를 사용해야하는 등 다른 순서로 tableview의 개인 모델을 변경했는지 이해할 수 있습니다.하지만 그 일은 일어나지 않습니다. 두 번째 "after"그림에서 세 번째와 네 번째 행은 반대 순서로되어 있습니다. 어떤 셀을 다시로드하든 상관하지 않습니다.

after one button push, delete-insert style

before state

after one button push, move-style

내 어휘 다채로운 저주 애플을 성장했다. 대신 저 자신을 저주해야합니까? 동일한 업데이트 블록 (행뿐만 아니라, 삽입 및 삭제)에서 행 재로드와 호환되지 않는 행이 있습니까? 버그 보고서를 제출하기 전에 누구나 나를 깨달을 수 있습니까?

+0

매우 흥미 롭습니다! –

+0

당신은 이것에 대한 해결책을 찾았습니까? 나는 똑같은 문제를 겪고있다. –

+0

아니요! 나는 "충분하지 않은 정보"와 ios6에서 테스트 해달라고 요청한 버그 보고서를 제출했다. (문제가 해결되지 않았을 수도 있고, UICollectionView가 비슷한 문제를 가지고있을 수도있다. 문제가됩니다.) 두 가지 해결 방법은 다음과 같습니다. 두 개의 별도 begin/endUpdates 블록을 수행하고, 다시로드 한 다음 하나를 이동/삽입/삭제합니다. reloadRowsAtIndexPaths를 완전히 건너 뛰고 적절한 셀을 수동으로 찾아서 다시 채 웁니다. – rgeorge

답변

3

방금 ​​코드를 가지고 노는 시간을 보냈습니다. 나는 동의합니다. 그냥 작동하지 않는 것 같습니다.

이 전체 영역은 문서화가 잘되어 있지 않지만 실제로는 moveRowAtIndexPath:toIndexPath:을 재로드 메소드와 함께 사용할 수 있다고는하지 않습니다. 에서 행 삽입 및 행 삭제 메소드와 혼합 될 수 있다고 말합니다. 그 대신에 코드를 수정하면 작동하는 것 같습니다. 따라서 버그를 제기하지 않고 개선을 요청할 수 있습니다. 어느 쪽이든, 나는 분명히 그것을 레이다에게 보냈습니다.

+0

확인해 주셔서 감사합니다. 레이다 신청. 애플이 그것을 해결한다면, 나는 해결책을 추가 할 것이다. – rgeorge

관련 문제