iOS:文本字段委托,如何在处理表格视图中的行移动之前自动结束编辑?

Posted

技术标签:

【中文标题】iOS:文本字段委托,如何在处理表格视图中的行移动之前自动结束编辑?【英文标题】:iOS: Textfield delegate, how to end edit automatically before processing a row move in a table view? 【发布时间】:2013-12-13 10:34:02 【问题描述】:

在我的表格视图的编辑阶段,您可以在所有单元格中编辑UITextFields 并移动单元格。如果您更改某个文本字段的文本并立即将该文本字段或包含该文本字段的单元格移动到另一个 indexPath,则会出现一个小问题,因为该文本尚未保存。然后一切都搞砸了。

为了解决这个问题,我基本上想在开始行移动之前自动调用textFieldDidEndEditing。那应该有效吗?但是如何以编程方式正确结束文本字段的编辑?通过辞职第一响应者?我该怎么做?

My two relevant functions:
-(void)textFieldDidEndEditing:(UITextField *)textField

    self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
    //Did End editing is always called first after ending the editing either by enter or by clicking the done button. So this method saves the newly entered text
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
    MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];

    if(textField.text != mainCategory.name)
        mainCategory.name = textField.text;
    

    self.activeField = nil;

    [self stopSuspendAutomaticTrackingOfChangesInManagedObjectContextWithDelay:0.3f];


- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
      toIndexPath:(NSIndexPath *)destinationIndexPath;

    // Process the row move. This means updating the data model to correct the item indices.

    //reordering has been defined in the CoreDataViewController so the
    //FetchedResultsController doesn't mess up the reordering since he would update
    //the fetched results permanently while reordering
    self.reordering = YES;

    //Makes only a mutable copy of the array, but NOT the objects (references) within
    NSMutableArray *fetchedResults = [[self.fetchedResultsController fetchedObjects] mutableCopy];

    // Grab the item we're moving
    NSManagedObject *resultToMove = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath];

    // Remove the object we're moving from the array.
    [fetchedResults removeObject:resultToMove];
    // Now re-insert it at the destination.
    [fetchedResults insertObject:resultToMove atIndex:[destinationIndexPath row]];

    // All of the objects are now in their correct order. Update each
    // object's displayOrder field by iterating through the array.
    int i = 1;
    for (MainCategory *fetchedResult in fetchedResults)
    
        fetchedResult.position = [NSNumber numberWithInt:i++];
    

    // Save
    NSError *error = nil;
    [self.budgetDatabase.managedObjectContext save:&error];

    // re-do the fetch so that the underlying cache of objects will be sorted
    // correctly
    [self.fetchedResultsController performFetch:&error];
    [self.tableView reloadData];

    self.reordering = NO;

编辑:我的新代码,仍然无法正常工作:

- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
      toIndexPath:(NSIndexPath *)destinationIndexPath;


    if(self.activeField)
        [self saveTextFieldEntry:self.activeField];
    
    // Process the row move. This means updating the data model to correct the item indices.

    //reordering has been defined in the CoreDataViewController so the
    //FetchedResultsController doesn't mess up the reordering since he would update
    //the fetched results permanently while reordering
    self.reordering = YES;

    //Makes only a mutable copy of the array, but NOT the objects (references) within
    NSMutableArray *fetchedResults = [[self.fetchedResultsController fetchedObjects] mutableCopy];

    // Grab the item we're moving
    NSManagedObject *resultToMove = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath];

    // Remove the object we're moving from the array.
    [fetchedResults removeObject:resultToMove];
    // Now re-insert it at the destination.
    [fetchedResults insertObject:resultToMove atIndex:[destinationIndexPath row]];

    // All of the objects are now in their correct order. Update each
    // object's displayOrder field by iterating through the array.
    int i = 1;
    for (MainCategory *fetchedResult in fetchedResults)
    
        fetchedResult.position = [NSNumber numberWithInt:i++];
    

    // Save
    NSError *error = nil;
    [self.budgetDatabase.managedObjectContext save:&error];

    // re-do the fetch so that the underlying cache of objects will be sorted
    // correctly
    [self.fetchedResultsController performFetch:&error];
    [self.tableView reloadData];

    self.reordering = NO;


-(void)textFieldDidBeginEditing:(UITextField *)textField

    self.activeField = textField;


-(void)textFieldDidEndEditing:(UITextField *)textField

//    self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
    //Did End editing is always called first after ending the editing either by enter or by clicking the done button. So this method saves the newly entered text
//    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
//    MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
//
//    if(textField.text != mainCategory.name)
//        mainCategory.name = textField.text;
//    
//    
//    self.activeField = nil;

    [self saveTextFieldEntry:textField];

//    [self stopSuspendAutomaticTrackingOfChangesInManagedObjectContextWithDelay:0.3f];


- (void)saveTextFieldEntry:(UITextField *)textField

    self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
    MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];

    if(textField.text != mainCategory.name)
        mainCategory.name = textField.text;
    

    self.activeField = nil;

    [self stopSuspendAutomaticTrackingOfChangesInManagedObjectContextWithDelay:0.3f];

如何确保在行移动之前完成此保存过程?也许这就是它不工作的原因,因为它比移动慢?!

【问题讨论】:

【参考方案1】:

你可以声明一个实例变量,比如:

UITextField * selectedTextField;

并将其更改为:

- (void)textFieldDidBeginEditing:(UITextField *)textField 
    selectedTextField = textField;


- (void)textFieldDidEndEditing:(UITextField *)textField 
    selectedTextField = nil;

无论您在哪里执行需要退出活动文本字段的操作,请添加:

if (selectedTextField && [selectedTextField isFirstResponder]) 
      [selectedTextField resignFirstResponder];

【讨论】:

我很高兴它做到了,圣诞快乐 :) 谢谢!我正在使用幻灯片来删除行手势,当您仍在编辑单元格中的文本字段时,它的结果很奇怪。您的建议为我解决了这个问题!【参考方案2】:

首先为tableView的每个单元格中创建的每个textField分配一个唯一的标签值,然后使用方法textFieldDidBeginEditing:将标签的值与文本值一起存储在一个变量中,当用户移动到下一个 textField 或触发 textFieldDidEndEditing: 方法检查 textField.tag 值是否与已存储的值匹配。如果匹配,则使用已存储的标签值更新您想要的任何内容..

【讨论】:

天哪,这是真的..我工作太久了 :-) 谢谢提示! 当我们转向复杂的思维模式时会发生这种情况,有时小提示不会在脑海中出现,直到有人向我们发出嗡嗡声 祝您新年快乐 嗯,好吧,它仍然无法按预期工作:/ 我现在有我编辑中的代码,但在更改文本并立即移动未正确保存的行之后仍然存在..跨度> 您可以再做一件事,只需将其余文本字段的 userInteractionEnable 设置为 FALSE,直到不保存此文本字段数据。并在 textField 上添加一个工具栏。【参考方案3】:

将当前文本字段保存在UITextFieldDelegate 的属性中

- (void)textFieldDidBeginEditing:(UITextField *)textField; 

并在您的行移动函数中对保存的 textField 进行无效调用。

【讨论】:

以上是关于iOS:文本字段委托,如何在处理表格视图中的行移动之前自动结束编辑?的主要内容,如果未能解决你的问题,请参考以下文章

在表格视图单元格之间移动的文本

具有文本字段滚动问题的 iOS 表格视图

如何在编辑表格视图单元格中的文本字段时重新加载所有表格视图单元格 - iOS Swift

如何在表格视图 IOS 内的滚动视图中创建文本字段

滚动表格视图时删除的文本字段值?

如何使用文本字段处理表格视图单元格