Spec-Zone .ru
спецификации, руководства, описания, API

Библиотека Разработчика iOS

Разработчик

iOS 马上着手开发 应用程序 (Начинают Разрабатывать приложения для iOS Сегодня),

PDF
На этой странице

教程 : 添加数据

本教程以第二个教程 ( “教程 : 串联图” ) 中创建的项目为基础。您将用到从使用设计模式、使用 основа  ,  ToDoList 应用程序中添加对动态数据的支持。

本教程讲述了以下操作 :

  • Основа 使用常见的 类

  • 创建自定数据类

  • 实现委托和数据源协议

  • 在视图控制器之间传递数据

完成本教程中的所有步骤后 , 您的应用程序外观大致是这样的 :

image: ../Art/ios_simulator_add_new_item_2x.png
image: ../Art/ios_simulator_full_list_checked_2x.png

创建数据类

现在就开始吧 , 请在 XCode 中打开您的现有项目。

 ,  ToDoList  , 

应用程序的目标在于创建一个待办事项列表 , 因此首先您将创建一个自定类 XYZToDoItem 来表示单个待办事项。您应该记得 ,XYZToDoItem 类已经在编写自定类中讨论过。

创建 XYZToDoItem 类

  1. 选取 «Файл»> «Новый»> «Файл» ( 或按下 Команда-N) 。

    这时将会出现一个对话框 , 提示您为新文件选取模板。

  2. 从左侧的 iOS 下方选择 “Касание Какао” 。

  3. 选择 “Класс Objective C” , 并点按 «Следующий» 。

  4. 在 «Класс» 栏中 , 在 XYZ 前缀后键入 ToDoItem。

  5. 从 “Подкласс” 弹出式菜单中选取 «NSObject» 。

    如果您完全按照本教程操作 , 那么在这个步骤之前 , «Класс» 标题可能是 XYZToDoItemViewController。选取 NSObject 作为 “Подкласс” 后,Xcode 会知道您创建了一个正常的自定类 , 并移除了它先前添加的 ViewController 文本。

  6. 点按 «Следующий» 。

  7. 存储位置默认为您的项目目录。此处无需更改。

  8. «Группа» 选项默认为您的应用程序名称 «ToDoList» 。此处无需更改。

  9. «Цели» 部分默认选定您的应用程序 , 未选定应用程序的测试。好极了 , 这些都无需更改。

  10. 点按 «Создают» 。

XYZToDoItem 类很容易实现。它具有项目名称、创建日期 , 以及该项目是否已完成等属性。继续将这些属性添加到 XYZToDoItem 类接口。

配置 XYZToDoItem 类

  1. 在项目导航器中 , 选择 XYZToDoItem.h。

  2. 将以下属性添加到该接口 , 使声明如下所示 :

    1. @interface XYZToDoItem : NSObject
    2. @property NSString *itemName;
    3. @property BOOL completed;
    4. @property (readonly) NSDate *creationDate;
    5. @end

检查点 : 通过选取 «продукт»> «Сборка» ( 或按下 Команда-B) 来生成项目。尽管该新类尚未实现任何功能 , 但是生成它有助于编译器验证任何拼写错误。如果发现错误 , 请及时修正 : 通读编辑器提供的警告或错误 , 然后回顾本教程中的说明 , 确保所有内容与此处的描述相符。

载入数据

您现在有一个类 , 可以用它作为基础来为单个列表项目创建并储存数据。您还需要保留一个项目列表。在 XYZToDoListViewController 类中跟踪此内容较为合适 , 视图控制器负责协调模型和视图 , 所以需要对模型进行引用。

Основа 框架有一个 NSMutableArray 类, 很适合跟踪项目列表。此处必须使用可变数组 , 这样用户就可以将项目添加到数组。因为不可变数组 NSArray 在其初始化后将不允许添加项目。

要使用数组 , 您需要声明并创建它。可以通过分配并初始化数组来完成。

要分配并初始化数组

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

    由于项目数组是表格视图控制器的实现细节 , 所以应该在.m 文件中进行声明 , 而不是.h 文件。此操作可让项目数组成为您自定类的私有数组。

  2. 将以下属性添加到接口类别中 , 它是由 XCode 在您的自定表格视图控制器类中创建的。声明应该是这样的 :

    1. @interface XYZToDoListViewController ()
    2. @property NSMutableArray *toDoItems;
    3. @end
  3. 在 viewDidLoad 方法中分配并初始化 toDoItems 数组 :

    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. self.toDoItems = [[NSMutableArray alloc] init];
    5. }

viewDidLoad 的实际代码中有一些附加行被注释掉了 , 那些行是 XCode 创建 XYZListViewController 时插入的。保留与否都没有影响。

现在 , 您已经拥有了一个可以添加项目的数组。添加项目将在单独的方法 loadInitialData 中进行 , 并将通过 viewDidLoad 调用该方法。由于此代码是一个模块化任务,所以会进入其自身的方法中。当然您也可以将方法分离出来,从而提高代码的可读性。在真正的应用程序中,此方法可能会从某种永久储存形式载入数据,例如文件。现在,我们的目标是了解表格视图如何处理自定数据项目,那么让我们创建一些测试数据来体验一下吧。

以创建数组的方式创建项目 : 分配并初始化。然后 , 给项目命名。该名称将显示在表格视图中。按照此方法创建一组项目。

载入初始数据

  1. 在 @implementation 行下方 , 添加一个新方法 loadInitialData。

    1. - (void)loadInitialData {
    2. }
  2. 在此方法中 , 创建几个列表项目 , 并将它们添加到数组。

    1. - (void)loadInitialData {
    2. XYZToDoItem *item1 = [[XYZToDoItem alloc] init];
    3. item1.itemName = @"Buy milk";
    4. [self.toDoItems addObject:item1];
    5. XYZToDoItem *item2 = [[XYZToDoItem alloc] init];
    6. item2.itemName = @"Buy eggs";
    7. [self.toDoItems addObject:item2];
    8. XYZToDoItem *item3 = [[XYZToDoItem alloc] init];
    9. item3.itemName = @"Read a book";
    10. [self.toDoItems addObject:item3];
    11. }
  3. 在 viewDidLoad 方法中调用 loadInitialData。

    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. self.toDoItems = [[NSMutableArray alloc] init];
    5. [self loadInitialData];
    6. }

检查点 : 通过选取 «продукт»> «Сборка» 来生成项目。您应该会在 loadInitialData 方法的代码行上看到大量错误。第一行是出错的关键所在 , 错误提示应该是 “Использование необъявленного идентификатора XYZToDoItem” 。这说明编译器在编译 XYZToDoListViewController 时不知道 XYZToDoItem。编译器比较特别 , 您需要明确告知它应当注意什么。

让编译器注意您的自定列表项目类

  1. 在 XYZToDoListViewController.m 文件的顶部附近找到 #import "XYZToDoListViewController.h" 行。

  2. 紧接着在其下方添加以下行 :

    1. #import "XYZToDoItem.h"

检查点 : 通过选取 «продукт»> «Сборка» 来生成项目。项目生成时应该没有错误。

显示数据

目前 , 表格视图具有一个可变数组 , 预填充了几个示例待办事项。现在您需要在表格视图中显示数据。

通过让 XYZToDoListViewController 成为表格视图的数据源 , 可以实现这一点。无论要让什么成为表格视图的数据源 , 都需要实施 UITableViewDataSource 协议。需要实施的方法正是您在第二个教程中注释掉的那些。创建有效的表格视图需要三个方法。第一个方法是 numberOfSectionsInTableView:, 它告诉表格视图要显示几个部分。对于此应用程序 , 表格视图只需要显示一个部分 , 所以实现比较简单。

在表格中显示一个部分

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

  2. 如果您在第二个教程中注释掉了表格视图数据源方法 , 现在请移除那些注释标记。

  3. 模板实现的部分如下所示。

    1. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    2. {
    3. #warning Potentially incomplete method implementation.
    4. // Return the number of sections.
    5. return 0;
    6. }

    更改为 ,  0  1 

  4. 更改 numberOfSectionsInTableView: 数据源方法以便返回单个部分 , 像这样 :

    1. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    2. {
    3. // Return the number of sections.
    4. return 1;
    5. }

下一个方法 tableView:numberOfRowsInSection: 告诉表格视图要在给定部分中显示几行。现在表格中有一个部分 , 并且每个待办事项在表格视图中都应该有它自己的行。这意味着行数应该等于 toDoItems 数组中的 XYZToDoItem 对象数。

返回表格中的行数

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

  2. 您可看到模板实现的部分是这样的 :

    1. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    2. {
    3. #warning Incomplete method implementation.
    4. // Return the number of rows in the section.
    5. return 0;
    6. }

    您想要返回所拥有的列表项目的数量。幸运的是 ,NSArray 有一个很方便的方法 , 称为 count, 它会返回数组中的项目数 , 因此行数是 [self.toDoItems count]。

  3. 更改 tableView:numberOfRowsInSection: 数据源方法 , 使其返回正确的行数。

    1. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    2. {
    3. // Return the number of rows in the section.
    4. return [self.toDoItems count];
    5. }

最后一个方法 ,tableView:cellForRowAtIndexPath: 元 请求一个单 格来显示给定行。到现在为止 , 您只是处理了代码 , 但是界面的绝大部分是针对行显示的单 元 格。幸运的是 ,Xcode 可让您轻松地在 соединяют интерфейсом с разработчиком 中设计自定单 元 格。首个任务是设计您的单 元 格, 并告诉表格视图不要使用静态内容 , 而要使用具有动态内容的原型单 元 格。

配置表格视图

  1. 打开串联图。

  2. 在大纲中选择表格视图。

  3. 选定表格视图后 , 在实用工具区域中打开 «Атрибуты» 检查器 image: ../Art/inspector_attributes_2x.png。

  4. 在 «приписывает» 检查器中 , 将表格视图的 «содержание» 属性从 “статические ячейки” 更改为 “динамические прототипы” 。

Соедините интерфейсом с разработчиком 会采用您配置的静态单 元 格, 并将它们全部转换为原型。原型单 元 格, 顾名思义 , 是使用您要显示的文本样式、颜色、图像或其他属性进行配置 , 并在运行时从数据源获取其数据的单 元 格。数据源会为每一行载入一个原型单 元 格, 然后配置该单 元 格来显示该行的数据。

元 要载入正确的单 格, 数据源需要知道单 元 格的名称 , 并且该名称也必须在串联图中进行配置。

设定原型单元格名称时,也将配置另一个属性—单元格选择样式,该样式用于确定用户轻按单元格时单元格的外观。将单元格选择样式设定为“None”,使用户轻按单元格时单元格不会高亮显示。这是当用户轻按待办事项列表中的项目,将其标记为已完成或未完成时,您想要单元格呈现的行为。稍后会在本教程中实现该功能。

元 配置原型单 格

  1. 元 在表格中选择第一个表格视图单 格。

  2. 在 «Атрибуты» 检查器中 , 找到 «Идентификатор» 栏并键入 ListPrototypeCell。

  3. 在 «Атрибуты» 检查器中 , 找到 «Выбор» 栏并选取 «Ни один» 。

元 您也可以更改原型单 格的字体或其他属性。基本配置很容易完成 , 您可以轻松记下。

下一步是实现 tableView:cellForRowAtIndexPath: 方法,让数据源为给定行配置单元格。表格视图在想要显示给定行时会调用此数据源方法。对于行数较少的表格视图,所有行可能会同时出现在屏幕上,所以表格中的每一行都会调用此方法。但是,行数很多的表格视图在给定时间内只会显示全部项目中的一小部分。最有效的方式是让表格视图仅请求要显示行的单元格,而这一点可通过 tableView:cellForRowAtIndexPath: 让表格视图实现。

对于表格中的任何给定行 , 取回 toDoItems 数组中的相应条目 , 然后将单 元 格的文本标签设定为项目的名称。

元 在表格中显示单 格

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

  2. 找到 tableView:cellForRowAtIndexPath: 数据源方法。模板实现是这样的 :

    1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    2. {
    3. static NSString *CellIdentifier = @"Cell";
    4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    5. // Configure the cell...
    6. return cell;
    7. }

    元 该模板执行多个任务。它会创建一个变量来保存单 格的标识符 , 向表格视图请求具有该标识符的单 元 格, 添加一个注释注明配置该单 元 格的代码应该写在哪里 , 然后返回该单 元 格。

    要让此代码为您的应用程序所用 , 需要将标识符更改为您在串联图中设定的标识符 , 然后添加代码来配置该单 元 格。

  3. 元 将单 格标识符更改为您在串联图中设定的标识符。为了避免拼写错误 , 请将串联图中的标识符拷贝并粘贴到实现文件中。该单 元 格标识符行现在应该是这样的 :

    1. static NSString *CellIdentifier = @"ListPrototypeCell";
  4. 在 возвращают 语句前 , 添加以下代码行 :

    1. XYZToDoItem *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
    2. cell.textLabel.text = toDoItem.itemName;

您的 tableView:cellForRowAtIndexPath: 方法应如下图所示 :

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. static NSString *CellIdentifier = @"ListPrototypeCell";
  4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
  5. XYZToDoItem *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
  6. cell.textLabel.text = toDoItem.itemName;
  7. return cell;
  8. }

检查点 : 运行您的应用程序。您在 loadInitialData 元 中添加的项目列表应该在表格视图中显示为单 格。

将项目标记为已完成

如果无法将待办事项列表中的项目标记为已完成,那么这个待办事项列表还不够好。现在,让我们来添加这样的支持。一个简单的界面应该可以在用户轻按单元格时切换完成状态,并在已完成的项目旁边显示勾号。幸运的是,表格视图附带了一些内建行为,您可以利用这些行为来实现这样的简单界面。需要注意的是,在用户轻按单元格时,表格视图要通知它们的委托。所以我们的任务是写一段代码,对用户轻按表格中的待办事项这个操作作出响应。

您在串联图中配置 XYZToDoListViewController 时,Xcode 就已经让它成为表格视图的委托了。您要做的只是实现 tableView:didSelectRowAtIndexPath: 委托方法 , 使其响应用户轻按 , 并在适当时候更新您的待办事项列表。

元 选定单 格后 , 表格视图会调用 tableView:didSelectRowAtIndexPath: 委托方法 , 来查看它应如何处理选择操作。在此方法中 , 您需要编写代码来更新待办项目的完成状态。

将项目标记为已完成或未完成

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

  2. 将以下代码行添加到文件末尾 , 在 @end 行正上方 :

    1. #pragma mark - Table view delegate
    2. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    3. {
    4. }

    请试着键入第二行 , 而不是拷贝和粘贴。您将发现代码补全是 XCode 最节省时间的功能之一。当 XCode 显示出可能的补全建议列表时 , 请滚动浏览列表 , 找到想要的建议 , 然后按下 возвращают 键。 XCode 会为您插入整行。

  3. 您想要响应轻按 , 但并不想让单 元 格保持选定状态。添加以下代码 , 让单 元 格在选定后立即取消选定 :

    1. [tableView deselectRowAtIndexPath:indexPath animated:NO];
  4. 在 toDoItems 数组中搜索相应的 XYZToDoItem。

    1. XYZToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
  5. 切换被轻按项目的完成状态。

    1. tappedItem.completed = !tappedItem.completed;
  6. 告诉表格视图重新载入您刚更新过数据的行。

    1. [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

您的 tableView:didSelectRowAtIndexPath: 方法应如下图所示 :

  1. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. [tableView deselectRowAtIndexPath:indexPath animated:NO];
  4. XYZToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
  5. tappedItem.completed = !tappedItem.completed;
  6. [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  7. }

检查点 : 运行您的应用程序。您在 loadInitialData 元 中添加的项目列表在表格视图中显示为单 格。但当您轻按项目时 , 并没有任何反应。为什么呢 ?

元 原因是您尚未配置显示项目完成状态的表格视图单 格。要实现此功能 , 您需要回到 tableView:cellForRowAtIndexPath: 方法 , 并配置单 元 格以在项目完成时显示指示。

指示项目已完成的一种方式是在其旁边放置一个勾号。幸运的是 , 表格视图右边可以有一个单 元 格附属物。默认情况下 ,单 元 格中没有任何附属物 ; 不过您可以进行更改 , 使其显示不同的附属物。其中的一个附属物就是勾号。您要做的是根据待办事项的完成状态 , 设定单 元 格的附属物。

显示项目的完成状态

  1. 前往 tableView:cellForRowAtIndexPath: 方法。

  2. 元 在设定单 格的文本标签的代码行下方添加以下代码 :

    1. if (toDoItem.completed) {
    2. cell.accessoryType = UITableViewCellAccessoryCheckmark;
    3. } else {
    4. cell.accessoryType = UITableViewCellAccessoryNone;
    5. }

您的 tableView:cellForRowAtIndexPath: 方法现在应如下图所示 :

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. static NSString *CellIdentifier = @"ListPrototypeCell";
  4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
  5. XYZToDoItem *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
  6. cell.textLabel.text = toDoItem.itemName;
  7. if (toDoItem.completed) {
  8. cell.accessoryType = UITableViewCellAccessoryCheckmark;
  9. } else {
  10. cell.accessoryType = UITableViewCellAccessoryNone;
  11. }
  12. return cell;
  13. }

检查点 : 运行应用程序。您在 loadInitialData 元 中添加的项目列表在表格视图中显示为单 格。轻按项目时 , 其旁边应该出现一个勾号。如果您再次轻按同一项目 , 勾号会消失。

添加新项目

构建待办事项列表应用程序功能的最后一步是实现添加项目的能力。当用户在 XYZAddToDoItemViewController 场景的文本栏中输入项目名称 , 并轻按 «Сделанный» 按钮时 , 您想要视图控制器创建一个新的列表项目并将其传递回 XYZToDoListViewController, 以显示在待办事项列表中。

首先 , 您需要拥有一个列表项目来进行配置。就像表格视图那样 , 视图控制器是将界面连接到模型的逻辑位置。为 XYZAddToDoItemViewController 添加一个属性来保存新的待办事项。

将 XYZToDoItem 添加到 XYZAddToDoItemViewController 类

  1. 在项目导航器中 , 选择 XYZAddToDoItemViewController.h。

    由于稍后需要从表格视图控制器访问列表项目 , 所以务必将其设为公共属性。这就是为什么要在接口文件 XYZAddToDoItemViewController.h 中声明它 , 而不在实现文件 XYZAddToDoItemViewController.m 中声明的原因所在。

  2. 将 импортируют 声明添加到 @interface 行上方的 XYZToDoItem 类中。

    1. #import "XYZToDoItem.h"
  3. 将 toDoItem 属性添加到该接口。

    1. @interface XYZAddToDoItemViewController : UIViewController
    2. @property XYZToDoItem *toDoItem;
    3. @end

要获得新项目的名称 , 视图控制器需要访问用户输入名称的文本栏。要实现此功能 , 请创建从 XYZAddToDoItemViewController 类到串联图中的文本栏的连接。

将文本栏连接到视图控制器

  1. 在大纲视图中 , 选择 XYZAddToDoItemViewController 对象。

  2. 点按窗口工具栏右上角的 «Ассистент» 按钮 , 打开辅助编辑器。

    image: ../Art/assistant_editor_2x.png

    右边的编辑器出现时 , 应该显示有 XYZAddToDoItemViewController.m。如果未显示 , 请点按右边的编辑器中的文件名 , 并选取 XYZAddToDoItemViewController.m。

    辅助编辑器可让您一次打开两个文件 , 以便能够在它们之间执行操作。例如 , 在源文件中键入一个属性 , 而源文件的对象又在接口文件中。

  3. 在串联图中选择文本栏。

  4. Управление 按住 键从画布上的文本栏拖到右边编辑器中的代码显示窗口 , 到达 XYZAddToDoItemViewController.m 中的 @interface 行正下方时停止拖移。

    image: ../Art/assistant_editor_drag_2x.png
  5. 在出现的对话框中 , 为 «Имя» 栏键入 “textField”。

    让选项的其余部分保持不变。您的对话框应如下图所示 :

    image: ../Art/configure_text_field_outlet.pdf
  6. 点按 «Подключение» 。

    XCode 会将必要的代码添加到 XYZAddToDoItemViewController.m, 用于储存指向文本栏的指针 , 并配置串联图来设置该连接。

另外 , 您需要知道何时创建项目。如果想要仅在 «Сделанный» 按钮被轻按时才创建项目 , 那么请将 «Сделанный» 按钮添加为 Выход 。

将 «Сделанный» 按钮连接到视图控制器

  1. 在串联图中 , 打开辅助编辑器 , 将最右边的窗口设定为 XYZAddToDoItemViewController.m。

  2. 在串联图中选择 «Сделанный» 按钮。

  3. Управление 按住 键从画布上的 «Сделанный» 按钮拖到右边的编辑器中的代码显示窗口 , 到达 XYZAddToDoItemViewController.m 中的 textField 属性正下方的行时停止拖移。

  4. 在出现的对话框中 , 在 «Имя» 栏键入 “doneButton”。

    保持选项的其余部分不变。对话框应如下图所示 :

    image: ../Art/configure_done_button_outlet_2x.png
  5. 点按 «Подключение» 。

您现在有了识别 «Сделанный» 按钮的方式。由于想在轻按 «Сделанный» 按钮时创建一个项目 , 所以需要知道该按钮何时被按下。

当用户轻按 «Сделанные» 按钮时 , 它会启动一个 раскручивают segue, 返回到待办事项列表 , 这正是您在第二个教程中配置的接口。在, непосредственно переходят 执行前 , 系统通过调用 prepareForSegue:, 给所包含的视图控制器一次准备机会。这便是检查用户是否轻按了 «Сделанный» 按钮的时候。如果是 , 将会创建一个新的待办事项。您可以检查轻按了哪一个按钮 , 如果是 «Сделанный» 按钮 , 将会创建项目。

轻按 «Сделанный» 按钮后创建项目

  1. 在项目导航器中选择 XYZAddToDoItemViewController.m。

  2. 在 @implementation 行下方添加 prepareForSegue: 方法 :

    1. - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    2. {
    3. }
  3. 在此方法中 , 请查看 «Сделанный» 按钮是否按下。

    如果未按下就不存储项目 , 而是让方法返回但不执行任何其他操作。

    1. if (sender != self.doneButton) return;
  4. 查看一下文本栏中是否有文本。

    1. if (self.textField.text.length > 0) {
    2. }
  5. 如果有文本 , 将会创建一个新项目 , 并用文本栏中的文本为其命名。另外 , 请确保完成状态被设定为 “NOfalse”。

    1. self.toDoItem = [[XYZToDoItem alloc] init];
    2. self.toDoItem.itemName = self.textField.text;
    3. self.toDoItem.completed = NO;

    如果没有文本 , 您就不需要存储项目 , 也不需要执行任何其他操作。

您的 prepareForSegue: 方法应如下图所示 :

  1. - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
  2. {
  3. if (sender != self.doneButton) return;
  4. if (self.textField.text.length > 0) {
  5. self.toDoItem = [[XYZToDoItem alloc] init];
  6. self.toDoItem.itemName = self.textField.text;
  7. self.toDoItem.completed = NO;
  8. }
  9. }

既然创建了一个新项目 , 那么就需要将该项目传递回 XYZToDoListViewController, 以便它可以将项目添加到待办事项列表。要完成此功能 , 请重新访问您在第二个教程中编写的 unwindToList: 方法。当用户轻按 «Отмена» 或 «Сделанный» 按钮 ,XYZAddToDoItemViewController 场景会在关闭时调用该方法。

就像作为 раскручивают переход 目标的所有方法一样 ,unwindToList: 方法也采用 непосредственно переходят переход 作为参数。 参数是从 XYZAddToDoItemViewController 展开并返回到 XYZToDoListViewController 的过渡。由于 непосредственно переходят 是两个视图控制器之间的过渡 , 所以知道它的源视图控制器是 XYZAddToDoItemViewController。通过向 непосредственно переходят 对象请求其源视图控制器 , 您可以用 unwindToList: 方法访问储存在源视图控制器中的任何数据。目前 , 您想要访问 toDoItem。如果它是 nil, 则该项目并未创建。原因可能是文本栏没有文本 , 或者是用户轻按了 «Отмена» 按钮。如果 toDoItem 有值 , 则可以取回该项目 , 再添加到 toDoItems 数组 , 并通过重新载入表格视图中的数据将其显示在待办事项列表中。

储存并显示新项目

  1. 在项目导航器中 , 选择 XYZToDoListViewController.m。

  2. 将 импортируют 声明添加到 @interface 行上方的 XYZAddToDoItemViewController 类中。

    1. #import "XYZAddToDoItemViewController.h"
  3. 找到您在第二个教程中添加的 unwindToList: 方法。

  4. 在此方法中 , 取回源视图控制器 XYZAddToDoItemViewController, 即您要展开的控制器。

    1. XYZAddToDoItemViewController *source = [segue sourceViewController];
  5. 取回控制器的待办事项。

    1. XYZToDoItem *item = source.toDoItem;

    这就是轻按 «Сделанный» 按钮时创建的项目。

  6. 看看这个项目是否存在。

    1. if (item != nil) {
    2. }

    如果是 nil, 可能是 «Отмена» 按钮关闭了屏幕 , 或者是文本栏中没有文本 , 因此不必存储该项目。

    如果项目存在 , 请添加到 toDoItems 数组。

    1. [self.toDoItems addObject:item];
  7. 重新载入表格中的数据。

    因为表格视图不会跟踪其数据 , 所以数据源 ( 在这个程序中是表格视图控制器 ) 有责任通知表格视图何时有新数据供其显示。

    1. [self.tableView reloadData];

您的 unwindToList: 方法应如下图所示 :

  1. - (IBAction)unwindToList:(UIStoryboardSegue *)segue
  2. {
  3. XYZAddToDoItemViewController *source = [segue sourceViewController];
  4. XYZToDoItem *item = source.toDoItem;
  5. if (item != nil) {
  6. [self.toDoItems addObject:item];
  7. [self.tableView reloadData];
  8. }
  9. }

检查点 : 运行您的应用程序。现在 , 当您点按添加按钮 (+) 并创建一个新项目时 , 它应该会显示在待办事项列表中。恭喜您 ! 您已经创建了一个应用程序 , 它能接收用户的输入 , 将其储存在对象中 , 并在两个视图控制器之间传递该对象。对于基于串联图的应用程序 , 这是在场景之间移动数据的基础。

小结

您差不多完成了开发 iOS 应用程序的入门之旅。最后一部分更详细地讲述了如何查询文稿材料 , 并且为您学习创建更高级的应用程序给出了一些后续建议。