2

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

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

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

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

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

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

4

2 回答 2

0

这是一个艰难的决定——View Controller Guide 建议在概念上似乎更清晰,但另一种方法可能更容易,特别是如果您使用的是 Core Data。为了给出一个笼统的概括意见,如果您使用的是 Core Data,我会说使用您的第一种方法,因为托管对象固有地具有自己的上下文并且可以更新自己(以及NSFetchedResultsController可以自动响应更新的类)。

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

//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.

于 2010-04-26T03:08:30.250 回答
0

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.

于 2010-04-26T16:37:51.307 回答