使用 Core Data 使用 didSelectRowAtIndexPath 编辑 TableView 单元格

Posted

技术标签:

【中文标题】使用 Core Data 使用 didSelectRowAtIndexPath 编辑 TableView 单元格【英文标题】:Editing a TableView Cell with didSelectRowAtIndexPath Using Core Data 【发布时间】:2013-11-28 15:33:40 【问题描述】:

我一直在关注 Stack Overflow 上的一些指南和问题,但没有通过基本的表格视图编辑获得想要的结果。

我有一个应用程序,它是一个表格视图控制器。如果我按下加号按钮,它会弹出一个视图控制器,允许我向 4 个文本字段(和一个日期选择器)添加信息。当我保存它时,它会保存到 Core Data 并且表格视图会显示信息。我现在希望能够简单地点击表格视图中的单元格,被带到另一个视图控制器并在需要时编辑单元格。此视图控制器看起来与添加视图控制器相同。

目前在 Detail 视图中,它没有向我显示 textField 中的值,并且 NSLog 返回 NULL。

在表格视图中,我使用 NSFetchedResultsController 填充数据库中的信息,并且来自 App Delegate 的 NSManagedContext 如下:

- (NSManagedObjectContext *)managedObjectContext

    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate performSelector:@selector(managedObjectContext)])
    
        context = [delegate managedObjectContext];
    
    return context;


- (NSFetchedResultsController *)fetchedResultsController

    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

    if (_fetchedResultsController != nil)
    
        return _fetchedResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Information" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"date.historyDate" ascending:NO];
    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"date.historyDate" cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;

CellforRow =

cell.textLabel.text = information.vendor;
cell.detailTextLabel.text = information.type; 

我的 didSelectRowAtIndexPath 方法如下:

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath


    DetailViewController *detailViewController = [[DetailViewController alloc] init];
    Information *selectedInformation = [self.fetchedResultsController objectAtIndexPath:indexPath];
    detailViewController.selectedInformation = selectedInformation;     
    [self.navigationController pushViewController:detailViewController animated:YES];

DetailViewController 有一个 Information 属性:

@property (nonatomic, strong) Information *selectedInformation; 

Detail 中的 viewDidLoad 如下所示:

- (void)viewDidLoad

    [super viewDidLoad];
    self.title = self.selectedInformation.vendor;
    self.editingNameField.text = self.selectedInformation.vendor;

    NSLog(@"%@", self.editingNameField.text);

编辑:更新为包含 prepareForSegue

NSIndexPath *indexPath = [self.timelineTableView indexPathForCell:sender];
Information *selectedInformation = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([segue.identifier isEqualToString:@"Editable Cell"])

    DetailViewController *selectedInformationTVC = [segue destinationViewController];

    [selectedInformationTVC setSelectedInformation:selectedInformation];

调用setSelectedInformation: - (void)setSelectedInformation:(Information *)selectedInformation self.title = self.selectedInformation.vendor;

self.editingNameField.text = self.selectedInformation.vendor;
NSLog(@"%@", self.editingNameField.text);

我没有同时使用 didSelectRow 和 prepareForSegue,它是其中之一,但都给出了相同的结果。

NSLog 给我 NULL 并且当视图控制器确实出现在屏幕上时,它在该字段中没有任何信息。

我在情节提要中使用了这个新的视图控制器,所以我不确定是否应该使用 prepareForSegue,但这也不起作用。

我的问题是 - 我是否需要在 DetailViewController 中对 Core Data 进行某种获取?

我需要做什么才能让它工作?

谢谢!

【问题讨论】:

如果你使用segue,你应该使用prepareForSegue。显示该代码。 谢谢@Wain - 我已经更新了代码以反映这一点 【参考方案1】:

您的两种方法都有不同的问题:

当您使用didDeselectRowAtIndexPathviewDidLoad 时,您的问题是您正在创建一个从未放置在屏幕上的视图控制器(因为segue 创建了一个不同的视图控制器)。

当您使用prepareForSegue 时,您的问题是您调用setSelectedInformation 并立即尝试与editingNameField 进行交互,而这还不存在(因为尚未加载视图)。

因此,您应该使用prepareForSegue,但您还需要使用viewDidLoad。将信息设置到目标视图控制器。在目标中,在视图加载后将该数据应用到视图。

最后,从调试的角度来看 - 记录源数据,而不仅仅是结果。这将引导您找到问题的根源。

【讨论】:

感谢@Wain - 做到了。我坚持使用 prepareForSegue 方法和使用 viewDidLoad,一切都顺利通过。非常感谢 - 非常感谢!【参考方案2】:

如果您使用storyBoards,您绝对应该在prepareForSegue 方法中进行信息转换,因为storyBoard 本身会实例化您的视图控制器。

在您的didSelect 方法中:

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

    Information *information = [self.fetchedResultsController objectAtIndexPath:indexPath];
    // Save your selected information for later
    self.selectedInformation = information;

在您的prepareForSegue 方法中:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    if ([segue.identifier isEqualToString:@"DetailViewSegue"])
    
        DetailViewController *dvc = (DetailViewController *)segue.destinationViewController;
        dvc.selectedInformation = self.selectedInformation;
    

应该这样做!

【讨论】:

感谢您的回复 - 我试过了,不幸的是仍然得到相同的结果,尽管现在 NSLog 看起来不像在运行,这意味着我可以理解为什么这不起作用。 NSLog 在 vi​​ewDidLoad 中。我在 TableView 中创建了一个 Information selectedInformation 属性,因此当我将 self.selectedInformation 放入 didSelect 时,它会调用它。我在 DVC 中也有一个信息 selectedInformation。我怀疑我们快到了!我现在正试图弄清楚为什么 NSLog 根本不运行 第一件事是,我使用了错误的方法 :) 我使用的是 didDESELECT .. - 现在可以使用您的代码,但它并没有一直给我选择的单元格..如果我有单元格 1 并单击它,它会显示单元格 1.. 如果我返回并单击单元格 2,它将再次显示单元格 1.. 如果我返回并单击单元格 3,它将显示单元格 2 我猜你可以在prepareForSegue的最后加上self.selectedInformation = nil

以上是关于使用 Core Data 使用 didSelectRowAtIndexPath 编辑 TableView 单元格的主要内容,如果未能解决你的问题,请参考以下文章

Swift:使用 tableView DidSelect 方法更改单元格的 UIButton 图像

如何在表格视图的 didSelect 上显示弹出框

在 Swift 3 中使用 didSelect 和 navigationController 在没有情节提要的情况下在 TableViewControllers 之间传递数据

在选择表格单元格“didSelect”时如何将图像解析到另一个视图?

如何在 didselect 上展开 collectionview 单元格以显示更多信息?

tableView didSelect 单元格不起作用