簡體   English   中英

將最后一行移出節並刪除節時出現奇怪的動畫

[英]Strange animation when moving last row out of section and deleting section

我有一個多部分的tableview。 在編輯模式下,我允許將行從一個部分移到另一部分。 將最后一行從一個部分中刪除后,我將刪除該部分。 所以我在moveRowAtIndexPath內部使用deleteSection。

當最后一個項目從節中移出時,節標題將按計划消失。 但是有一個非常奇怪的動畫錯誤,其中移動的行似乎與它上方的行“合並”,並且在“ to”部分的底部顯示一個空行(可能是因為該部分的numberOfRows為正確,但2行位於同一位置)。 甚至更陌生,當我單擊該行的重新排序控件(不移動項目,只需觸摸並釋放)時,兩個項目“合並”。

我發布了一個視頻來演示這一點。

我嘗試包裝我的數據更改並在開始/結束更新中查看更改,但無濟於事。

我已經在這里上傳了一個測試項目,我還將在下面發布代碼。 要點:

  • 我試圖在演示項目中復制數據源的格式,以防出現問題。 關鍵是我的源代碼是其他兩個數組的組合數組(盡管我看不到為什么會是個問題)。
  • 若要查看問題的行為,請將底部的兩行向上移動到頂部。 但是不要將它們放在頂部的最后一行中,因為這似乎可以正常工作。
  • 在本演示項目中,將行從頂部移動到底部的另一種方式是錯誤的。

代碼(所有這些都在演示項目中):

我在loadView中設置了數組:

- (void)loadView{
array1 = [NSMutableArray array];
[array1 addObject:@"test 0"];
[array1 addObject:@"test 1"];
[array1 addObject:@"test 2"];

    array2 = [NSMutableArray array];
    [array2 addObject:@"test a"];
    [array2 addObject:@"test b"];

    [super loadView];
}

我也有一個返回這些數組組合的方法-用作數據源:

- (NSMutableArray *)sourceArray{
NSMutableArray *result = [NSMutableArray array];
if (array1.count > 0) {
    [result addObject:array1];
}
if (array2.count >0) {
    [result addObject:array2];
    }
    return result;
}

這使得行/節的數量非常簡單:

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return self.sourceArray.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [[self.sourceArray objectAtIndex:section] count];
}

標准單元格/標題格式:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell.textLabel.text = [[self.sourceArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"Section %i", section];
}

這是我做魔術的地方

    // Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

        if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        }
    }

我注意到,來自待刪除部分的行將消失,直到您修改訂單控件。

我懷疑當tableview調用此數據源方法時,它的狀態仍處於執行移動的中間,因此調用'deleteSections'將使表嘗試刪除正在移動的行。 它並沒有太大的合並,因為它以與節標題相同的速率逐漸消失,而它下面的那個只是在回彈以填充空間。

輕擊控件會使表視圖重新調整自身位置,並意識到該行實際上並未消失。

要嘗試解決此問題,請嘗試通過調度調用在下一個runloop中運行刪除操作,例如:

if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
    dispatch_async(dispatch_get_main_queue(), ^() {
        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    });
}

這將導致刪除操作仍在主線程上運行,但允許'moveRow'及其碰巧發生的任何調用棧在刪除調用之前完成其邏輯

您的問題出在動畫上。 一個正在完成而另一個尚未完成(移動和刪除動畫),導致一個單元格被繪制在另一個單元格上。 您可以通過再次移動單元格來驗證這一點。 然后將顯示正確的順序。 根據Apple在UITableView上的文檔

注意:數據源不應在tableView:commitEditingStyle:forRowAtIndexPath:的實現中調用setEditing:animated:。 如果出於某種原因,它必須在延遲后通過使用performSelector:withObject:afterDelay:方法來調用它。

因此,要解決此問題,請對您的代碼執行以下操作:

if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
   [self performSelector:@selector(someMethod:) withObject:fromIndexPath afterDelay:1.0];
}

- (void) someMethod:(NSIndexPath *) fromIndexPath {
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section]  withRowAnimation:UITableViewRowAnimationFade];
}

應該工作正常。 只需將延遲更改為更適合您的時間即可。

我認為UITableViewRowAnimationFade動畫會干擾UITableViewCell移動動畫。 您可以嘗試做的一件事是延遲部分刪除,以使單元格移動行動畫完成。

嘗試用以下代碼替換您的代碼。

-(void)deleteSection:(NSIndexSet*)indexSet
{
    [self.tableView deleteSections:indexSet withRowAnimation:UITableViewRowAnimationFade];
}

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

    if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
        [self performSelector:@selector(deleteSection:) withObject:[NSIndexSet indexSetWithIndex:fromIndexPath.section] afterDelay:1.0];
//      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    }
}

在最后一行丟失動畫的解決方案:

if([listOfItemsOnTransaction count]==indexPath.row){ 
  [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]     
   withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView reloadData];
   }else
   {
       [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] 
         withRowAnimation:UITableViewRowAnimationFade];


   }

如果行或行中的內容可以引起焦點,您是否檢查過是否調用過resignFirstResponder[view endEditing:YES] 我們在使用文本字段時看到了這一點,並且(IIRC也依賴於iOS 4版本)將焦點放在其中一個字段上。

刪除該部分后,您必須重新加載tableview。 試試這個代碼。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

        if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView reloadData];
        }

    }

在代碼中交換fromArraytoArray的順序。 如果該項目從數組中取出具有現有的1一個保留計數,它將具有其添加到之前一個保留的0計數toArray

如果您交換訂單,則該項目將從保留計數1變為2,然后在刪除完成后返回1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM