在 iPhone 上使用模态视图控制器编辑属性时应使用哪种模式?

发布于 2024-08-30 02:12:01 字数 561 浏览 5 评论 0原文

我正在寻找一种通过 iPhone 上的模态视图执行基本属性编辑的良好模式。

假设我正在构建一个与“联系人”应用程序类似的应用程序。 “详细信息”视图控制器在 UITableView 中显示联系人的所有属性。当 UITableView 进入编辑模式时,单元格中会显示一个公开图标。单击单元格会导致模式“编辑器”视图控制器显示允许用户修改所选属性的视图。此视图通常仅包含一个文本框或选择器。用户单击“取消/保存”,“编辑器”视图将被关闭,“详细信息”视图将被更新。

在这种情况下,哪个视图负责更新模型?

“编辑器”视图可以使用键值编码直接更新属性。这出现在 CoreDataBooks 示例中。这在某种程度上对我来说是有意义的,因为它将属性视为编辑器视图控制器的模型。

然而,这不是视图控制器编程指南建议的模式。它建议“编辑器”视图控制器应该定义“详细信息”控制器采用的协议。当用户指示他们完成编辑时,将使用输入的值回调“详细信息”视图控制器,并关闭“编辑器”视图。使用这种方法,“详细”控制器更新模型。如果您对多个属性使用相同的“编辑器”视图,则这种方法似乎有问题,因为只有一个回调方法。

希望获得一些有关哪种方法最有效的反馈。

I am looking for a good pattern for performing basic property editing via a modal view on the iPhone.

Assume I am putting together an application that works like the Contacts application. The "detail" view controller displays all of the contact's properties in a UITableView. When the UITableView goes into edit mode a disclosure icon is displayed in the cells. Clicking a cell causes a modal "editor" view controller to display a view that allows the user to modify the selected property. This view will often contain only a single text box or picker. The user clicks Cancel/Save and the "editor" view is dismissed and the "detail" view is updated.

In this scenario, which view is responsible for updating the model?

The "editor" view could update the property directly using Key-Value Coding. This appears in the CoreDataBooks example. This makes sense to me on some level because it treats the property as the model for the editor view controller.

However, this is not the pattern suggested by the View Controller Programming Guide. It suggests that the "editor" view controller should define a protocol that the "detail" controller adopts. When the user indicates they are done with the edit, the "detail" view controller is called back with the entered value and it dismisses the "editor" view. Using this approach the "detail" controller updates the model. This approach seems problematic if you are using the same "editor" view for multiple properties since there is only a single call-back method.

Would love to get some feedback on what approach works best.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

反差帅 2024-09-06 02:12:01

我不认为任何 Apple 示例(或其他任何人的示例)实际上向您展示了如何构建整个现实世界的应用程序。相反,每个示例只是一个测试工具,它向您展示如何使用 API 的一项特定功能,但不关注该功能如何与其他功能真正集成。数据模型的转变特别短。

我更喜欢这样的设计,其中数据模型是应用程序的主干,所有视图控制器/视图对都由它负责。视图控制器不直接相互通信,而是通过数据模型进行通信。数据模型跟踪应用程序当前正在处理哪些信息,以及每个特定视图控制器在任何给定时间需要哪些数据。

让我们以联系人管理器类型的应用程序为例。数据模型的基础是联系人对象的列表,每个对象又包含联系人的属性。数据模型将完全控制对数据的访问并监视当前正在使用哪些数据。 UI 是分层的,用户首先在 masterView 中看到所有联系人的列表,然后在 contactDetailView 中看到每个联系人的详细信息,然后可以在自定义属性编辑视图中为每种类型的数据编辑每个联系人属性,因此有一个nameEditView、phoneDetailView、emailEditView 等。每个都有一个配对的视图控制器 masterVC、contactDetailVC、nameEditVC 等。

为了构建它的表视图,masterVC 向数据模型询问联系人的数量、它们的划分,然后请求每个特定的联系人每个特定索引路径上的对象,以便它可以显示一个表。当用户选择表行时,masterVC 通过向数据模型发送索引来告知数据模型选择了哪个联系人对象。然后masterVC推送contactDetailVC。它没有任何其他作用。

当 contactDetailVC 激活时,它会向数据模型询问当前活动的 Contact 对象。它不知道也不关心当前联系人是如何选择的,甚至也不知道它之前是哪个视图/VC。数据模型返回当前活动的联系人。当用户选择一个字段时,contactDetailVC 告诉数据模型选择了联系人的哪个属性,然后将适当的 editorVC 推送到堆栈上。

当 editorVC 加载时,它会询问当前联系人和当前正在编辑的属性的数据模型。它不知道也不关心当前联系人属性是如何选择的,甚至也不知道它之前是哪个视图/VC。当用户进行更改时,它会要求数据模型保存更改(如果由于某种原因验证失败,数据模型可以拒绝),然后自行弹出。

在内部,我喜欢将数据模型分为两个部分,每个部分由单独的对象管理。一个是抽象数据管理器本身,在本例中是核心数据堆栈。第二个是用户默认值管理器,用于跟踪数据模型中的实际操作状态并将其保存到用户默认值。主对象将这些对象作为属性保存并充当数据模型的接口。

这种类型的模型可以轻松地暂停、恢复或重新启动应用程序回到之前的状态。由于每个视图/VC 都是独立的,因此当您重新启动应用程序时,您只需将所有视图推送到堆栈上而无需动画,最后一个推送的视图会完全填充数据,即使用户在之前的视图中没有选择任何内容并且确实这样做了甚至看不到他们。

它还可以保护用户在崩溃时避免数据丢失,因为每个 VC 每次推送或弹出时都会保存其数据和应用程序状态。添加额外的视图/VC 很容易,因为每个 VC 只需了解数据模型并与之通信,而不需要一堆其他 VC。它使应用程序的组件易于在不同版本的应用程序或完全不同的应用程序中使用。

编辑:

你只是硬编码一些 if
配对属性的语句
使用正确的编辑器,或者您是
做一些更有活力的事情
实体/属性元数据?

在大多数最常见的设计中,联系人实体可以具有可变数量的电话号码、电子邮件或其他数据字段,因此每个属性实际上都是一个单独的实体,并且联系人将具有指向这些实体的关系。当用户在 ContactDetailView 中选择要编辑的联系人时,数据模型将简单地标记代表联系人所需属性的 NSManagedObject。它可以通过设置“lastChosenAttribute”之类的属性或存储对象的 URI 来实现此目的。当编辑器视图加载时,它将被硬编码以向数据模型询问“lastChosenAttribute”,并会收到电话号码、电子邮件等的 NSManagedObject。编辑器将对该对象进行更改,并且它们将自动保存回联系方式。

对于单一数据,例如名称或名称组件,数据模型将为 editorVC 提供联系人实体,并且 editorVC 将被硬编码以向联系人对象询问该特定属性。

I don't think any of the Apple examples (or anyone else's) actually show you how to structure an entire real world application. Instead, each example is just a test harness which shows you how to use one particular feature of the API but pays no attention to how that feature really integrates with anything else. Data models are given particularly short shift.

I prefer a design in which the data model is the spine of the application upon which hands all the view-controller/view pairs. The view controllers do not communicate with each other directly but instead communicate through the data model. The data model tracks what information the app is currently working on and therefore what data each particular view controller needs at any given time.

Let's use a contact manager type apps as an example. The basic of the data model would be a list of contact objects each of which in turn would hold attributes of a contact. The data model would completely control access to the data and monitors which data was currently being used. The UI is hierarchal such that the user first sees a list of all contacts in a masterView, then the details of each contact in a contactDetailView and then can edit each contact attribute in a custom attribute edit view for each type of data so there is a nameEditView, a phoneDetailView, an emailEditView etc. Each has a paired view controller masterVC, contactDetailVC, nameEditVC etc.

The to build it's tableview, the masterVC ask the data model for the number of contacts, their divisions into sections and then request each particular contact object at each particular index path so it can display a table. When the user selects a table row, the masterVC tells the data model which contact object was selected by sending it the index. Then the masterVC pushes the contactDetailVC. It does nothing else.

When the contactDetailVC activates, it ask the data model for the currently active Contact object. It doesn't know or care how the current contact was selected nor even which view/VC preceded it. The data model returns the currently active contact. When the user selects a field, the contactDetailVC tells the data model which attribute of the contact was selected and then pushes the proper editorVC onto the stack.

When the editorVC loads it ask for the data model for the current contact and the current attribute being edited. It doesn't know or care how the current contact attribute was selected nor even which view/VC preceded it. When the user makes a change, it ask the data model to save the change (the data model can refuse if verification fails for some reason) and then pops itself.

Internally, I like to implement the data model in two parts each managed by separate object. One is the abstracted data manager itself in this case a Core Data stack. The second is an user defaults manager that tracks the actual state of operations in the data model and saves them to user defaults. A master object holds these objects as attributes and serves as the interface of the data model.

This type of model makes it easy to suspend, resume or restart the application back to its previous state. Since each view/VC is self contained, when you restart the app, you just push all the views on the stack without animation and the last one pushed pops up fully populated with data even though the user chose nothing in the previous views and indeed did not even see them.

It also protects the user from data loss in the event of a crash since each VC saves its data and the app state every time it pushes or pops. It's easy to add additional view/VC because each VC only has to know about and communicate with the data model instead of bunch of other VC. It makes the components of the app easy to use in different versions of the app or in different apps altogether.

Edit:

Do you just hard code some if
statements to pair up the attributes
with the correct editor, or are you
doing something more dynamic based on
the entity/attribute metadata?

In most the most common design, the Contact entity could have a variable number of phone#s, emails or other data fields so each attribute would actually be a separate entity and the Contact would have a relationships pointing to those entities. When the user selected that contact to edit in the ContactDetailView, the data-model would simply mark the NSManagedObject representing the desired attribute of the contact. It could do so by setting an attribute like "lastChosenAttribute" or storing the URI for the object. When the editor view loaded it would be hard coded to ask the data-model for the "lastChosenAttribute" and would receive an NSManagedObject for a phone#, email etc. The editor would make changes to that object and they would be automatically saved back into the contact.

For data that is singular, such as a name or name components, the data-model would provide the editorVC with the contact entity and the editorVC would be hard coded to ask the contact object for that specific attribute.

初懵 2024-09-06 02:12:01

这是一个艰难的决定——视图控制器指南建议在概念上似乎更清晰,但其他方法可能更容易,特别是当您使用核心数据时。为了给出一个笼统的概括意见,如果您使用 Core Data,我会说使用您的第一种方法,因为托管对象本质上有自己的上下文并且可以更新自己(并且诸如 NSFetchedResultsController 之类的类可以自动响应更新)。

如果您不使用核心数据,我会采用“官方”建议,因为它可以更轻松地手动管理更新的属性。至于对多个属性的关注,当然可以有多个委托方法并调用适当的方法。例如:

//if property is an address
if ([self.delegate respondsToSelector:@selector(editorView:didUpdateAddress:)])
    [self.delegate editorView:self didUpdateAddress:theAddress];

//if property is a name
if ([self.delegate respondsToSelector:@selector(editorView:didUpdateName:)])
    [self.delegate editorView:self didUpdateName:theName];

不过,这可能很难管理——您可能希望有一个属性的抽象超类,或者类似的东西。

It's a tough call--the View Controller Guide recommendation seems cleaner conceptually, but the other method can be easier, especially if you're using Core Data. To give a blanket generalized opinion, I would say use your first method if you're using Core Data, since managed objects inherently have their own context and can update themselves (and classes such as NSFetchedResultsController can automatically respond to updates).

If you're not using Core Data, I would go with the "official" recommendation, since it makes it easier to manage updated properties manually. As to the concern about multiple properties, it's certainly possible to have multiple delegate methods and call the appropriate one. For instance:

//if property is an address
if ([self.delegate respondsToSelector:@selector(editorView:didUpdateAddress:)])
    [self.delegate editorView:self didUpdateAddress:theAddress];

//if property is a name
if ([self.delegate respondsToSelector:@selector(editorView:didUpdateName:)])
    [self.delegate editorView:self didUpdateName:theName];

This could get hard to manage, though--you'd probably want to have an abstract superclass for properties, or something along those lines.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文