3

所以我在核心数据上苦苦挣扎。我发现有很多方法可以做同样的事情,如果您尝试使用 Storyboards 和 UIManagedDocuments 构建应用程序,您需要阅读比去年更早的所有教程和示例以及翻译表。今天的问题是关于在添加新托管对象时找到最佳实践。我已经看到了两种方式的例子:

  1. 在表视图控制器中创建新的托管对象(单击 + 后)并将新的闪亮托管对象提供给从属的“添加”视图控制器,以获取所有对象属性的用户输入。这看起来很简单,而且返回的对象也很容易理解,因为它包含所有单独的属性。但是我在这个“添加”视图控制器中看到了一个“取消”按钮的示例代码,该按钮删除传入的托管对象,然后在关闭自身之前调用 Save Context。功能性,但是我肩上的 MVC 培训 gnome 对我大喊大叫,让这个从属的 Add View 删除一个对象,并且恐怖直接调用 Save Context。Apple 的 Recipe 示例代码似乎使用了这种方法。

  2. 不向添加视图控制器发送任何内容,并让它返回一个委托调用表视图控制器,该表视图控制器将每个属性作为单独的传递参数返回。所以返回方法变得很长:controller:(UIViewController *)controller didReturnFirstName:(NSString *)firstName andLastName:(NSString *)lastName andStreetAddress:(NSString *) and... and... and.. But this is SO与 MVC 教条一致,因为托管对象在接收到所有单独的属性时在表视图控制器中重新创建,并且“添加”视图永远不会触及模型(核心数据),或者在用户更改时丢弃未使用的托管对象他们的心思。
    即使使用链式委托方法,我仍在与自己争论哪种方法更好。来自使用这两种形式的人的评论和想法将是一个受欢迎的补充。

谢谢。

4

4 回答 4

1

你是对的,有很多方法可以解决这个问题。

听起来好像你从一个可能无法保存的上下文开始,所以为了能够回到你的起点,我会这样处理它:

  1. 首先创建一个新的 NSManagedObject 用作​​传递给“编辑”视图的临时对象。
  2. 如果您正在编辑现有对象,请将现有对象中的属性复制到这个新的临时对象中(您可以使用快速 for 循环将它们全部复制)。否则继续新创建的对象。
  3. 将临时对象传递给“编辑”视图控制器,让它对这两种情况一视同仁。
    一个。如果用户按下取消,则有一个协议或委托方法通知 tableview 和 tableview 然后简单地丢弃临时对象。
    湾。如果他们按下保存,通知表格视图,然后将临时副本中的属性复制回原始对象并删除临时对象(如果是编辑操作),或者如果它是“添加”,则将其保留为新创建的对象“ 手术。
于 2012-05-01T23:19:48.867 回答
1

如果您查看 Apple教程中的示例,他们通过执行以下概述的许多事情来完成此任务,在这种情况下,他们有一个模式视图来输入要添加到数据模型中的信息:

  1. 在出现的模态视图中,他们创建了一个协议来处理关闭视图或保存数据以及实现该协议的类型 id 的属性作为委托,这确保了实现所需方法的任何对象

  2. 在创建模态视图的视图控制器中,它们实现协议,包括将对象保存到数据模型和关闭模态视图

  3. 在创建模态的视图控制器中,他们将创建模态视图的视图控制器设置为模态视图委托期间的模态视图委托

因此,总而言之,在模态视图中收集您需要的新数据:在 .h 中创建协议和属性并合成它

 @protocol yourProtocol <NSObject>;
 //methods that determine what happens based on what user does, it would save your core data object
 @end

 @property(nonatomic, weak) id<yourProtocol> delegate;

然后,在模态视图 .m 文件中,您可能会在委托上调用这些方法,可能是在它们选择保存或完成时,因此每个方法的一个方法可能是连接到按钮的 IBAction

 [self.delegate myMethod];

在呈现模态视图的视图中,您在 .h 文件中实现协议

 @interface viewController() <yourProtocol>

最后,将您的方法添加到显示模态视图的 .m 文件的视图控制器中,这应该包括删除视图并保存您的核心数据。根据Apple和其他消息来源,导致弹出/模式等的视图控制器应该是关闭它的视图控制器。然后,在使用序列缩进的序列中,将在模态视图中呈现的视图控制器设置为模态视图的委托。

于 2012-05-01T22:28:46.187 回答
0

这不是一个真正的答案,所以可以随意忽略,但其他任何一个(到目前为止)都不是一个完整的答案,我觉得有必要在不创建新问题的情况下添加一些观点,因为我真的很想了解这也是底部。特别是答案应该处理

  • 当您取消与保存时会发生什么
  • 如果您想使用同一个控制器来编辑现有实体而不是创建新实体怎么办

尼克斯的答案涉及苹果(当前)传回数据的约定,但不是一个完整的答案,因为该教程不处理核心数据托管对象,而苹果自己的样本确实使用托管对象的做法有所不同。

但是在这个问题上,我发现委托约定在某些情况下很笨拙,并且很高兴从更有经验的开发人员那里阅读: http ://robsprogramknowledge.blogspot.pt/2012/05/back-segues.html

Rob 详细介绍了所有同样有效的不同机制,包括协议/委托约定(Nick's),使用没有协议的数据对象(所谓的“共享内存”) - 更像其他一些人建议的,以及 - 我的最喜欢的 - 使用块。块是一个不错的选择,因为虽然它像委托一样工作,但代码完全保留在“父”视图控制器源中的上下文中

但是,“共享内存”更有意义,因为正如您所说,使用您已经设计用于传递所有这些属性的数据(托管)对象以外的任何东西似乎很愚蠢。

那么我的问题是,创建这些托管对象的约定是什么,传递它们,然后要么 1. 保存更改 2. 取消更改 3. 完全取消创建新实体

Inafzigers 上面的回答是这样的,但是为什么要复制所有属性呢?我不能不保存我的更改吗?

Apple 的 CoreDataBooks 似乎通过在 prepareForSegue 和委托方法(当它返回时)中创建ManagedObjectContext 和该上下文中的新实体(insertNewObjectForEntityForName)来处理这个问题: - 如果单击“保存”,它会同时保存这个新实体ManagedObjectContext 和父 FetchedResultsContext 来存储对象 - 如果单击 Cancel 它什么也不做,有效地丢弃新的托管对象上下文,因此,大概,新对象

所以这可能是传统的方法,除了:

  • 该示例的代码 (CoreDataBooks RootViewController.m) 中有一条注释指出两个托管上下文不是必需的,这意味着您可以只用一个来执行相同的操作。这是完整的评论: 重要提示:没有必要为此使用第二个上下文。您可以只使用现有的上下文,这将简化一些代码——例如,您不需要执行两次保存。但是,此实现说明了一种有时可能有用的模式(您想要维护一组单独的编辑)。

  • CoreDataBooks 不使用 UIManagedDocument - 不确定这是否会有所不同

我不清楚的是,我们真的要使用 insertNewObjectForEntityForName 来创建托管对象吗?如果用户点击保存,那么只创建对象然后仅在稍后插入它呢?

另外,如果我们进行编辑和取消,我们可以使用撤消管理器来消除更改吗?

于 2012-09-26T18:50:51.270 回答
0

我认为正确的方法实际上是NSManagedObjectContext为您的 AddController(如果要创建新项目)或 EditController(如果要修改现有项目)创建一个新的、单独的。

根据您的 SDK 选择 A) 或 B):

A) 然后您可以选择在该上下文中保存更改,或丢弃该上下文。

在“保存”的情况下,您可以通过 Notifications ( ) 将更改合并到 TableController 中。ManagedObjectContextNSManagedObjectDidSaveNotification

在“取消”的情况下,您可以丢弃单独的上下文。

B) 或者,如果您使用的是 OSX 10.7(+),您可以使用嵌套NSManagedObjectContext的 s,在 AddController(子上下文)中创建一个NSManagedObjectContext,并将它的 parentContext 设置为 TableController 的NSManagedObjectContext.

在“保存”的情况下,您将保存子上下文和父上下文。

在“取消”的情况下,您只需丢弃子上下文。

在 Apple 的 CoreDataBooks 示例中查看详细示例http://developer.apple.com/library/ios/#samplecode/CoreDataBooks/Introduction/Intro.html

于 2012-05-01T21:17:46.670 回答