2013-09-27 3 views
0

정확히 20 개 항목 (게임의 인벤토리 크기)이있는 비교적 간단한 UITableView가 있습니다. 내 맞춤 표 셀은 항목을 포함하지 않는 인벤토리 슬롯을 나타냅니다. 솔루션을 가지고 있지만이를 처리 할 수있는 더 좋은 방법이 있는지 알고 싶었습니다.UITableView에서 항목 삭제 (제거하지 않고)

의도 된 결과

과 같을 수 있습니다 사용자의 재고 : 사용자가 변기를 삭제

Bellybutton fuzz 
Petrified weasel snout 
Chocolate covered toilet seat 
Coupon for a high-five from Chase 
SLOT 5 EMPTY 
SLOT 6 EMPTY 
. 
. 
. 
SLOT 20 EMPTY 

경우 목록은 다음과 같아야합니다

Bellybutton fuzz 
Petrified weasel snout 
Coupon for a high-five from Chase 
SLOT 4 EMPTY 
SLOT 5 EMPTY 
. 
. 
. 
SLOT 20 EMPTY 

주 리스트에는 여전히 삭제 된 후에 사용 된 셀이 인벤토리의 상위 3 개 슬롯을 차지하도록 위로 이동 한 후 20 개의 셀이 포함됩니다.

내 최초의 시도가 사용하는 것이었다 문제는 새로운 콘텐츠 반영하기 위해 [tableView deleteRowsAtIndexPaths:withRowAnimation:]를 사용하여 내 백업 데이터를 조정 (한 적은 재고 항목, 하나 개의 추가 빈 슬롯을.) 그러나이었다

, 이것은로 추락 다음 예외 (?)

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'Invalid update: invalid number of rows in section 0. The number of rows 
contained in an existing section after the update (20) must be equal to the number 
of rows contained in that section before the update (20), plus or minus the number 
of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or 
minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' 

용액

[참고 번째의 코드 섹션은 명확성을 위해 실제 코드에서 크게 단순화되어 있습니다. 문제는 특정 구현 세부 사항이 아닌 솔루션 기술에 대한 것입니다.] 결국 내게 해킹 같은 느낌이 들지만 실제로 않습니다. 의도 한 결과를 얻는다.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     NSDictionary *item = [self itemForRowAtIndexPath:indexPath]; 
     if (!item) return; 

     // Keep track of the deleted item count 
     self.mDeletedEntries += 1; 

     [tableView beginUpdates]; 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop]; 
     [tableView endUpdates]; 

     // Remove it from the data store 
     [Inventory removeInventoryItem:item]; 
    } 
} 

이 그런 후, 나는이 누락 된 항목 대체 : 항목을 삭제

은 다음과 같습니다

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // If we have deleted some entries and need to add some new ones, schedule 
    // a process to insert them. 
    // 
    // *This is what feels like a hack to me* 
    if (self.mDeletedEntries) 
    { 
     [self performSelector:@selector(addEmptySlots:) withObject:tableView afterDelay:0]; 
    } 

    // Return the current count that IOS wants (inventory size minus the deleted ones) 
    return kUserMaxInventorySize - self.mDeletedEntries; 
} 

- (void)addEmptySlots:(UITableView *)tableView 
{ 
    // We start adding entries into the list at the end 
    int insertLocation = kUserMaxInventorySize - self.mDeletedEntries; 

    [tableView beginUpdates]; 

    // Add the deleted entries (should only ever be 1 entry, really)  
    for (int i = 0; i < self.mDeletedEntries; ++i) 
    { 
     // They get added to the end of the table 
     NSIndexPath *path = [NSIndexPath indexPathForRow:insertLocation + i inSection:0]; 
     NSArray *indexArray = [NSArray arrayWithObjects:path,nil]; 

     // Insert the entry. We don't need to actually add the item to our data store, 
     // since empty entries will simply report "Slot empty" text. 
     [tableView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationBottom]; 
    } 

    // These are no longer deleted 
    self.mDeletedEntries = 0; 

    [tableView endUpdates]; 
} 

이 작동을하지만,이이 작업을 수행하는 가장 좋은 방법입니다?

+0

: 배열에서 행을 삭제하고, 그것을 가지고 귀하의 tableview의 하단에 행을 추가하는 장소 세포. –

+0

처음에'SLOT % d EMPTY'를 포함하는 NS NSString 객체가 20 개인 간단한 NSMutableArray는 실제 객체로 객체 교체를 시작합니다. 삭제시 문자열로 다시 대체하십시오. –

+0

@HotLicks reloadData의 문제점은 목록에서 항목을 애니메이션으로 해제하는 기능이 손실된다는 것입니다. 나는 테이블의 맨 위로 이동하고 이미 맨 위에 있던 셀 뒤에 튀는 애니메이션을 실행하는 셀의 몇 가지 매우 이상한 결과를 포함하여 이것과 함께 많은 다른 문제가있었습니다. 아주 이상한 것. – pauln

답변

0

나는 당신의 접근 방식이 복잡하다고 생각합니다. 예를 들어, 귀하의 tableview 항상 정확히 20 셀을 것이라고 말했다. 왜`- (NSInteger) tableView : (UITableView *) tableView numberOfRowsInSection : (NSInteger) 섹션 '이 단순히 20을 반환합니까?

인벤토리에 항목을 저장하는 방법에 대해 잘 모르겠습니다. 인벤토리 이름의 NSMutableArray를 가지고있는 것처럼 예제를 작성하려고합니다.

나는 단순히 행의 개수로 20을 반환합니다.당신이 항목을 삭제하면

– tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    ... 
    if ([indexPath row] < [inventory count]) { 
     // configure a cell that represents actual inventory 
     NSDictionary *item = [inventory objectAtIndex:[indexPath row]]; 
     ... 
    } else { 
     // configure a "SLOT * EMPTY" cell 
     NSUInteger slotNumber = [indexPath row] - [inventory count] + 1; 
     ... 
    } 
    ... 
} 

제거 : 항목이 당신이 또는 당신이 "SLOT EMPTY"셀을 작성해야하는 경우 셀을 만드는 행을 존재하는 경우 cellForRowAtIndexPath 검사에서

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return 20; 
} 

확인합니다 삭제 신경 쓰지 않는 - 난 그냥 테이블의 백업 데이터와 reloadData를 업데이트 할 거라고 생각

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     // Remove it from the data store 
     [inventory removeObjectAtIndex:[indexPath row]]; 

     [tableView beginUpdates]; 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop]; 
     // you also need to insert a row at the bottom so the number of rows is correct 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:19 inSection:0] withRowAnimation:UITableViewRowAnimationTop]; 
     [tableView endUpdates]; 
    } 
} 
+0

감사합니다. Alex! 당신은 절대적으로 옳습니다. 재고 항목을 제거한 업데이트 프로세스 중에 항목을 삽입 할 생각이 없었습니다. 필자의 경우 트릭은 목록의 끝 부분이 아니라 마지막 실제 재고 항목 (삭제 후) 바로 다음에 새 항목을 삽입하는 것이 었습니다. 그러나 구현에 따라 다릅니다. – pauln

+0

내가 도울 수있어서 기쁩니다! – Alex

관련 문제