简体   繁体   English

什么是NSManagedObjectContext最佳实践?

[英]What are NSManagedObjectContext best practices?

I'm working with a Navigation Controller based iOS app. 我正在使用基于导航控制器的iOS应用程序。 There are multiple tableView screens that pull and save data from a Core Data persistent store. 有多个tableView屏幕可以从Core Data持久性存储中提取和保存数据。 Most of the data for the different table views comes from NSFetchedResultsController instances or NSFetchRequests. 不同表视图的大多数数据来自NSFetchedResultsController实例或NSFetchRequests。

The app works as intended but I have been getting a few random crashes and glitches that seem to be related to Core Data. 该应用程序按预期工作,但我得到了一些似乎与核心数据相关的随机崩溃和故障。 For example sometimes when I save the context the app will crash but not always. 例如,有时当我保存上下文时,应用程序会崩溃,但并非总是如此。 Another thing I've been seeing is the very first tableView doesn't always update the reflect the data that was modified in it's detail view. 我一直看到的另一件事是第一个tableView并不总是更新反映在其详细视图中修改的数据。

Currently I'm passing around a single Managed Object Context that was created in the app delegate to each of the different view controllers by setting the context property of the view controller just before I push it onto the navigation stack. 目前,我正在通过在将其推入导航堆栈之前设置视图控制器的context属性,将在app委托中创建的单个Managed Object Context传递给每个不同的视图控制器。

This seems like a clunky, hacky way of getting the job done. 这似乎是一种笨重,笨拙的完成工作的方式。 Is there a better design pattern to use? 是否有更好的设计模式可供使用?

I noticed in one of the WWDC sessions using delegation but I've never used creating my own delegates before and haven't been able to puzzle it out of the WWDC session. 我在其中一个使用委托的WWDC会话中注意到,但我以前从未使用过创建自己的委托,也无法将其从WWDC会话中解脱出来。

Thanks. 谢谢。

=) =)

Use singleton NSManagedObjectContext for all Controllers isn't a best practice. 对所有控制器使用singleton NSManagedObjectContext不是最佳实践。

Each Controller should have your own Context to manage specific, sometimes atomic, operations at document store. 每个Controller都应该有自己的Context来管理文档存储中的特定(有时是原子)操作。

Think if you can edit a NSManagedObject attached to Controller that pass the same Context to other Controller that will select another instance to delete or edit.. you can lost the controll about modified states. 想想你是否可以编辑一个附加到Controller的NSManagedObject,它将相同的Context传递给其他Controller,它将选择另一个要删除或编辑的实例..你可能会丢失有关修改状态的控制。

When you create a view controller, you pass it a context. 创建视图控制器时,将向其传递上下文。 You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. 您传递现有上下文,或者(在您希望新控制器管理一组离散编辑的情况下)为您创建的新上下文。 It's typically the responsibility of the application delegate to create a context to pass to the first view controller that's displayed. 应用程序委托通常负责创建上下文以传递给显示的第一个视图控制器。

http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html

1) Use a singleton for your CoreData setup (NSPesistentStoreCoordinator, NSManagedObjectModel & NSManagedObjectContext). 1)使用单例进行CoreData设置(NSPesistentStoreCoordinator,NSManagedObjectModel和NSManagedObjectContext)。 You can use this singleton to execute the fetch requests you created in your Models and to add or delete Entities to your Context. 您可以使用此单例执行在模型中创建的获取请求,以及向上下文添加或删除实体。

2) Delegates are not that hard. 代表们并不那么难。 Following is a sample: 以下是一个示例:

@class SomeClass

@protocol SomeClassDelegate <NSObject> //Implements the NSObject protocol
- (void) someClassInstance:(SomeClass *)obj givesAStringObject:(NSString *)theString;
- (BOOL) someClassInstanceWantsToKnowABooleanValue:(SomeClass *)obj //Call to delegate to get a boolean value

@optional
- (NSString *) thisMethodIsOptional; 

@end

@interface SomeClass : NSObject {
   id<SomeClassDelegate> delegate;
   //Other instance variables omitted.
}
@property (assign) id<SomeClassDelegate> delegate;
@end

@implementation SomeClass
@synthesize delegate;
- (void) someMethodThatShouldNotifyTheDelegate {
   NSString *hello = @"Hello";
   if (self.delegate != nil && [self.delegate respondsToSelector:@selector(someClassInstance:givesAStringObject:)]) {
      [self.delegate someClassInstance:self givesAStringObject:hello];
   }
}
@end

Option 1 could be something like this, you will have to setup the variables in the init of the object (and implement the singleton ofcourse): 选项1可能是这样的,你将不得不在对象的init中设置变量(并实现单例ofcourse):

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface CoreDataUtility : NSObject {
@private
    NSManagedObjectModel *managedObjectModel;
    NSManagedObjectContext *managedObjectContext;
    NSPersistentStoreCoordinator *persistentStoreCoordinator;
}

+ (CoreDataUtility *)sharedCoreDataUtility;
- (NSEntityDescription *) entityDesctiptionForName:(NSString *)name;
- (NSMutableArray *) executeRequest:(NSFetchRequest *)request;
- (id) getInsertedObjectForEntity:(NSString *)entity;
- (void) deleteAllObjects:(NSString *) entityName;
- (void) deleteManagedObject:(NSManagedObject *)object;
- (void) saveContext;

@end

Currently I'm passing around a single Managed Object Context that was created in the app delegate to each of the different view controllers...This seems like a clunky, hacky way of getting the job done. 目前我正在传递一个托管对象上下文,该托管对象上下文是在应用程序委托中创建的,每个不同的视图控制器......这看起来像是一种笨重,笨拙的方式来完成工作。 Is there a better design pattern to use? 是否有更好的设计模式可供使用?

There's nothing particularly special about a managed object context in this respect, it's just another object that your view controller may need to do its job. 在这方面,托管对象上下文没有什么特别之处,它只是视图控制器可能需要完成其工作的另一个对象。 Whenever you're setting up an object to perform a task, there are at least three strategies that you can use: 每当您设置一个对象来执行任务时,您至少可以使用三种策略:

  1. Give the object everything it needs to get the job done. 为对象提供完成工作所需的一切。

  2. Give the object a helper that it can use to make decisions or get additional information. 为对象提供一个帮助程序,可以用它来做出决策或获取其他信息。

  3. Build enough knowledge about other parts of the application into the object that it can go get the information it needs. 将有关应用程序其他部分的足够知识构建到可以获取所需信息的对象中。

What you're doing right now sounds like the first strategy, and I'd argue that it's often the best because it makes your view controllers more flexible, less dependant on other parts of the app. 你现在正在做的事情听起来像是第一个策略,我认为它通常是最好的,因为它使你的视图控制器更灵活,更少依赖于应用程序的其他部分。 By providing the MOC to your view controllers, you leave open the possibility that you might someday use that same view controller with a different context. 通过向视图控制器提供MOC,您可能有一天可能会使用具有不同上下文的相同视图控制器。

Jayallengator makes the helpful observation that every managed object has a reference to its context, and if you're passing around specific managed objects you don't also need to pass along the context. Jayallengator提供了有用的观察结果,即每个托管对象都有对其上下文的引用,如果您传递特定的托管对象,则不需要传递上下文。 I'd take that a step further: if you're passing specific managed objects to your view controller, the view controller often won't need to know about the context at all. 我更进一步:如果您将特定的托管对象传递给视图控制器,视图控制器通常根本不需要知道上下文。 For example, you might keep Game objects in your data store, but a GameBoardViewController will probably only care about the one Game that's being played, and can use that object's interface to get any related objects (Player, Level, etc.). 例如,您可能将Game对象保留在数据存储中,但GameBoardViewController可能只关心正在播放的一个Game,并且可以使用该对象的接口来获取任何相关对象(Player,Level等)。 Perhaps these observations can help you streamline your code. 也许这些观察可以帮助您简化代码。

The second strategy is delegation. 第二个战略是授权。 You'll usually use a protocol when you use delegation, so that your object knows what messages it can send its helper without knowing anything else about the helper. 当您使用委托时,通常会使用协议,以便您的对象知道它可以发送其帮助程序的消息,而无需了解有关帮助程序的任何其他信息。 Delegation is a way to introduce a necessary dependency into your code in a limited, well-defined way. 委派是一种以有限的,明确定义的方式在代码中引入必要依赖的方法。 For example, UITableView knows that it can send any of the messages defined in the UITableViewDelegate protocol to its delegate, but it doesn't need to know anything else about the delegate. 例如,UITableView知道它可以将UITableViewDelegate协议中定义的任何消息发送给它的委托,但是它不需要知道委托的任何其他内容。 The delegate could be a view controller, or it could be some other kind of object; 委托可以是视图控制器,也可以是其他类型的对象; the table doesn't care. 桌子不在乎。 The table's delegate and data source are often the same object, but they don't have to be; 表的委托和数据源通常是同一个对象,但它们不一定是; again, the table doesn't care. 再次,表不关心。

The third strategy is to use global variables or shared objects (which is what people usually mean when they talk about singletons). 第三种策略是使用全局变量或共享对象(这是人们在谈论单身时通常所说的)。 Having a shared object that you can access from anywhere in your code is certainly easy, and you don't have that "klunky" extra line of code that configures your object, but it generally means that you're locking your view controllers in to using that shared object and no other. 拥有一个可以从代码中的任何位置访问的共享对象当然很容易,并且您没有配置对象的“klunky”额外代码行,但它通常意味着您将视图控制器锁定到使用该共享对象而不是其他。 It's a lot like gluing a hammer to your hand because you know for certain that that hammer is the tool you need. 这很像是将锤子粘在手上,因为你肯定知道那把锤子是你需要的工具。 Works great for pounding nails, but it can be painful if you later discover that you'd like to use the same hand for driving screws or eating dinner. 适用于敲击指甲,但如果您后来发现您想用同一只手驱动螺丝或吃晚餐,这可能会很痛苦。

The singleton approach seems to be best-practice, but another trick I found useful was that in cases where you're passing a NSManagedObject from one view controller to the next anyway (usually as an instance variable), you don't need to also pass the NSManagedObjectContext since you can get the context from the object you passed in by invoking [myManagedObject managedObjectContext]. 单例方法似乎是最佳实践,但我发现另一个有用的技巧是,在你将NSManagedObject从一个视图控制器传递到另一个视图控制器的情况下(通常作为实例变量),你也不需要传递NSManagedObjectContext,因为您可以通过调用[myManagedObject managedObjectContext]从传入的对象获取上下文。 This can be a handy shortcut when there's maybe only one or two methods where you need the context and you don't want the overhead of creating yet another NSManagedObjectContext ivar/property. 当可能只有一两个方法需要上下文并且您不希望创建另一个NSManagedObjectContext ivar / property的开销时,这可以是一个方便的快捷方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM