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"그림에서 세 번째와 네 번째 행은 반대 순서로되어 있습니다. 어떤 셀을 다시로드하든 상관하지 않습니다.
내 어휘 다채로운 저주 애플을 성장했다. 대신 저 자신을 저주해야합니까? 동일한 업데이트 블록 (행뿐만 아니라, 삽입 및 삭제)에서 행 재로드와 호환되지 않는 행이 있습니까? 버그 보고서를 제출하기 전에 누구나 나를 깨달을 수 있습니까?
매우 흥미 롭습니다! –
당신은 이것에 대한 해결책을 찾았습니까? 나는 똑같은 문제를 겪고있다. –
아니요! 나는 "충분하지 않은 정보"와 ios6에서 테스트 해달라고 요청한 버그 보고서를 제출했다. (문제가 해결되지 않았을 수도 있고, UICollectionView가 비슷한 문제를 가지고있을 수도있다. 문제가됩니다.) 두 가지 해결 방법은 다음과 같습니다. 두 개의 별도 begin/endUpdates 블록을 수행하고, 다시로드 한 다음 하나를 이동/삽입/삭제합니다. reloadRowsAtIndexPaths를 완전히 건너 뛰고 적절한 셀을 수동으로 찾아서 다시 채 웁니다. – rgeorge