将单元格数组项传递给另一个视图控制器

Posted

技术标签:

【中文标题】将单元格数组项传递给另一个视图控制器【英文标题】:Pass cell array item to another view controller 【发布时间】:2015-04-28 12:29:32 【问题描述】:

所以这是我一直在阅读的一个常见问题,我还在学习,所以请记住这一点。

基本上,我的应用程序目前允许您向表格视图添加一个项目,然后当您从表格视图中选择一个单元格时,它会显示另一个视图控制器,用于显示该单元格的详细信息。

Diagram

在我的 tableView 实现文件 .m 中,我有代码可以在单击单元格时转到视图控制器:

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

    SelectedItemViewController *selectView = [[SelectedItemViewController alloc] initWithNibName:@"SelectedView" bundle:nil];

    [selectView.titleView setText:@"test"];

    [self performSegueWithIdentifier:@"showSelected" sender:indexPath];

'setText' 段代码只是我测试,看看我是否能够更改 ViewCellController 中的 textLabel。

当用户保存一个新项目时,这是以下在返回 TableView 时调用的 segue 代码。 'toDoItem' 是一个 NSMutableArray。

 -(IBAction)unwindToList:(UIStoryboardSegue *)segue 
    AddToDoItemViewController* source = [segue sourceViewController];
    ToDoItem* item = source.toDoItem;
    if (item != nil)
        [self.toDoItems addObject:item];
        [self.tableView reloadData];
    

显然我做错了什么。

我想了解的是如何做到:

    选择一个单元格,从数组中的该索引中获取数据,因此不仅仅是单元格数据,数据包括:标题、描述、DueDate 和完成。

    在另一个视图控制器中显示它。

    处理完成布尔值并将其保存,以便再次单击时保持原样。

我不想要一个完整的答案,只是为了给我指明正确的方向,这样我就可以自己解决了,谢谢!

【问题讨论】:

你的阵列是什么? Title、Description、DueDate 和 completion 这些值包含哪些内容? 它将对象添加到数组中,即:NSString* itemName; NSString* 项目描述; NSDate* itemDueDate; BOOL 完成; 你想把这些细节传递给其他视图控制器吗?/ 是的。表格单元格被选中 > detailView 显示上面的信息 参考这个文档。它显示了使用 StoryBoard appcoda.com/… 传递数据 【参考方案1】:

据我了解,您处于简单的 Tableview 详细情况。

您有一个项目列表,并且希望在下一个视图中保留一个特定项目,以便您可以显示它的详细信息(或编辑,或以某种方式进行交互)。

例如,我正在考虑联系人列表或食谱列表。你有一份餐食清单,你可以看到它们的标题和等级,并说你想看成分,你必须点击它。

如果我在这里错了,请纠正我,否则,这很简单。

您需要一个表格视图(在UITableViewController 或简单的UIViewController 中添加您自己的表格视图)。无论哪种方式,您的 tableview 显然已经完成,所以我可以跳过那部分。此控制器应位于 UINavigationController 中,这应该是您唯一的导航控制器。我会直言不讳地说,如果你是初学者(和我一样),你可能会在一段时间内制作只有一个导航控制器的应用程序。

您还有一组自定义对象,您肯定有。假设它是一个Contact,你有一个Contact 对象数组。

当您构建您的表格视图时,您使用该联系人数组并相应地制作您的单元格。

这是一个非常简短的例子:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *identifier = @"ContactCell";

    //I'm assuming you're using a custom cell    
    ContactCell *cell     = [self.tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) 
        cell = [[ContactCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    


    Contact *contact = [_dataArray objectAtIndex:indexPath.row];
    cell.nameLabel.text = contact.name;     
    cell.phoneNumberLabel.text = contact.phone;
    return cell;


这只是一个简短的例子来说明我的观点;请注意,您必须设置数据源和委托,以及其他方法 (-numberOfRowsInSection:) 才能使 tableview 正常工作。

好的,您有一个联系人列表和一个带有他们电话号码的小文本,但您想显示他们的地址或您的数组中已有但尚未显示的任何内容。所有这些数据都已加载,您真的很想展示它。一个很好的用途确实是点击单元格并推送另一个视图。推送很好,因为您可以使用操作系统为您创建的后退按钮,这就是您需要 UINavigationController

的原因

要处理这个问题,您需要两个方法,首先是 tableview 方法 didSelectRowAtIndexPath,然后是 prepareForSegue

有很多方法可以解决这个问题,但我会尝试做一些简单的事情。你想知道你点击了哪个项目,你想把它交给下一个视图。所以,好吧,要将它提供给下一个视图,您需要先拥有它。我们会:

在数组中查找 保留对它的某种引用(它是索引路径或整个项目) 通过它

您可以使用ivar 来保留该引用,有更好/不同的方法,但这很简单。其他人可能想用不同的风格做出自己的答案,或者在我的答案结束时用另一种方式编辑我的答案。

ivar 只是 .m 文件顶部的一个实例变量,您可以在该 .m 文件的任何位置访问它。它有点像@property,但只有那个类/控制器才能看到。

您可以在控制器的最顶部使用它,该行应该已经在 viewDidLoad 之前,只需添加花括号和您的变量。

@implementation MyTableViewController

    Contact *_myContactToPass;

下面的方法只会找到项目并调用“传递”方法

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

    _myContactToPass = [_dataArray objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:@"fromTableViewToDetails" sender:self];

DetailsViewController 中,您的.h 文件中需要一个@property,它是一个Contact 对象,以及一些标签和按钮以及您需要的所有优质爵士乐。使用 _contact 属性填充所有这些标签,因为您总是会在加载该视图之前传递它,所以它们将从所选联系人加载动态数据,而不是从情节提要中加载静态标签。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

   if([segue.identifier isEqualToString:@"fromTableViewToDetails"])

        DetailsViewController *vc = (DetailsViewController*)segue.destinationViewController;
        vc.contact = _myContactToPass;  

注意事项:

我假设您在情节提要中创建了一个名为 fromTableViewToDetails 的 push segue 我假设您知道如何做到这一点

我很失望你找不到一个简单的 tableview 教程来向自己学习,这对任何开发人员来说都是非常重要的一步:搜索、阅读、尝试、重试、学习。 我已经尽可能详细地回答了你的问题,但一个简单的谷歌搜索会引导你到现在你会记住的令人惊叹的网站:

AppCoda.com

RayWenderlich.com

一旦您知道如何使用他们的静态数据教程,您就可以阅读另一篇关于数据库的教程,然后简单地将两者混合使用。尽管我确信有很多教程会一步一步完整地展示如何将数据加载到数组中、显示它、编辑/删除其中的一些以及永久地重新保存它。

一旦您对所有这些感到满意,您就可以开始阅读有关 Core data 的内容(一开始有点难以处理,但非常棒),或者只是 FMDBSQLite。如果我可以给你一个建议,不要单独使用 Sqlite,使用 FMDB 包装器。 sqlite3 只是从头开始编写代码非常痛苦。

希望这会有所帮助。 :)

【讨论】:

您好,感谢您的建议。在过去的 4 个小时里,我一直在研究,并且一直在对我拥有的一些现有代码尝试不同的东西。对于学校的任务,我们还没有使用数据库,但最终会使用。我已经设置了大部分应用程序,它只是试图获取数据,我在以前的应用程序中做过(将对象发送到另一个视图控制器),而不是通过带有对象数组的表视图。 然后按照我的指示,你应该没问题 :) 我已经提供了你需要的 90% 的信息,我相信你已经很好地处理了缺少的 10%。【参考方案2】:
    在您的 detailview 控制器中,您可以将 toDoItem 设置为弱属性... 在实例化 detailviewcontroller 后,在 mainviewcontroller 的 didselectrow 中,您可以将其 todoitem 设置为给定索引路径下 mainviewcontroller 中的 todoitem

在您的 detailviewcontroller 中,您将使用 mainviewcontroller 中的项目和

    在您的 unwind segue 中,您唯一需要做的就是重新加载 tableviews 数据。

希望你明白我的意思:)

【讨论】:

嘿,所以我在 detailView 中将 toDoItem 设为了一个弱属性,我在 .h 文件中通过创建一个新的@property 来做到这一点。我正在尝试使用 prepareSegue 方法中的 indexPath 将 toDoItem(detailedView)设置为 mainviewController toDoItem,但我遇到了“objectAtIndex”的问题 - 选择器没有已知的类方法。 在您的 prepareforsegue 中应该如下所示:1.SelectedItemViewController *selectView = segue.destinationViewController;, 2.selectView.toDoItem = self.toDoItems[indexPath.row];(或selectView.toDoItem = [self.toDoItems objectAtIndex:indexPath.row]; 是的,我有,只是忘了添加 self.toDoItem。所以我的 didSelectRowAtIndex 路径相同,然后我的 PrepareForSegue 代码与上面一样,但使用 if 语句确保其正确的 segue,我收到“以 NSException 类型的未捕获异常终止”错误。 你能和我分享你的代码,让我看看有什么问题吗? @Lizzeiy 请看一下。我做了一些小改动:dropbox.com/sh/hpvj5lgyxf27p5o/AADtaz_5MTuYeZj9AKTbuCbGa?dl=0

以上是关于将单元格数组项传递给另一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何将值传递给另一个视图控制器?

识别选择了哪个tableviewcell并将值传递给另一个视图控制器[重复]

通过 Collection View Cell Swift 中的 segue 将图像传递给另一个视图控制器

将数据从集合视图单元格移动到新的集合视图单元格

将按下的按钮传递给另一个 View JSON

试图将字符串数组传递给目标视图控制器