Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/44.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 核心数据:用于设置核心数据堆栈的UIManagedDocument或AppDelegate?_Iphone_Ios_Objective C_Core Data_Sdk - Fatal编程技术网

Iphone 核心数据:用于设置核心数据堆栈的UIManagedDocument或AppDelegate?

Iphone 核心数据:用于设置核心数据堆栈的UIManagedDocument或AppDelegate?,iphone,ios,objective-c,core-data,sdk,Iphone,Ios,Objective C,Core Data,Sdk,我对在哪里设置核心数据堆栈有点困惑。在Appdelegate中,或使用UIManagedDocument的共享实例,如下所述: 现在,我在AppDelegate中设置了by core数据堆栈,并在ViewController之间传递MOC。但是迁移到UIManagedDocument并创建一个共享实例是否更好,这样我就不必一直通过MOC了?另外,因为它较新的UIManagedDocument用于将数据(通常是文件)同步到iCloud。它只与核心数据有切点关系 核心数据设置通常在AppDelega

我对在哪里设置核心数据堆栈有点困惑。在Appdelegate中,或使用UIManagedDocument的共享实例,如下所述:


现在,我在AppDelegate中设置了by core数据堆栈,并在ViewController之间传递MOC。但是迁移到UIManagedDocument并创建一个共享实例是否更好,这样我就不必一直通过MOC了?另外,因为它较新的UIManagedDocument用于将数据(通常是文件)同步到iCloud。它只与核心数据有切点关系

核心数据设置通常在
AppDelegate
中完成,因此您在那里所做的没有任何错误。事实上,如果您使用核心数据创建一个新项目,那么Xcode模板就是这样做的

通常不需要将
ManagedObjectContext
从viewcontroller传递到viewcontroller。最好创建一个单例数据访问层,它可以在应用程序中的任何位置提供上下文。在某些情况下,您可能希望为viewcontroller使用专用MOC,但不太常见

下面是一些创建单例DataAccessLayer的代码:

DataAccessLayer.h

@interface DataAccessLayer : NSObject

   //Saves the Data Model onto the DB
   - (void)saveContext;

   //DataAccessLayer singleton instance shared across application
   + (id) sharedInstance;
   + (void)disposeInstance;
   // Returns the managed object context for the application.
   // If the context doesn't already exist, it is created and bound 
   // to the persistent store coordinator for the application.
   + (NSManagedObjectContext *)context;
@end
DataAccessLayer.m

#import "DataAccessLayer.h"

//static instance for singleton implementation
static DataAccessLayer __strong *manager = nil;

//Private instance methods/properties
@interface DataAccessLayer ()

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and 
// bound to the persistent store coordinator for the application.
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's 
// store added to it.
@property (readonly,strong,nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory;
@end


@implementation DataAccessLayer

@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;

//DataAccessLayer singleton instance shared across application
+ (id)sharedInstance
{
    @synchronized(self) 
    {
        if (manager == nil)
            manager = [[self alloc] init];
    }
    return manager;
}

+ (void)disposeInstance
{
    @synchronized(self)
    {
        manager = nil;
    }
}

+(NSManagedObjectContext *)context
{
    return [[DataAccessLayer sharedInstance] managedObjectContext];
}

//Saves the Data Model onto the DB
- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) 
    {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) 
        {
            //Need to come up with a better error management here.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and 
// bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
        return __managedObjectContext;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) 
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the 
// application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil) 
        return __managedObjectModel;

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" 
                                               withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] 
                         initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the 
// application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil) 
        return __persistentStoreCoordinator;

    NSURL *storeURL = [[self applicationDocumentsDirectory] 
                         URLByAppendingPathComponent:@"MyData.sqlite"];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
                                     initWithManagedObjectModel:[self managedObjectModel]];

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                           configuration:nil URL:storeURL options:nil error:&error]) 
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return __persistentStoreCoordinator;
}

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
                                         inDomains:NSUserDomainMask] lastObject];
}

@end
在需要上下文的任何时候,您都可以使用以下方法获取上下文:

NSManagedObjectContext *context = [DataAccessLayer context];
这种设计通常效果很好
NSManagedObjectContext
是一个非常轻量级的对象,因此不存在真正的性能损失。但是,如果您需要在其他线程上执行核心数据,那么设计需要做一些更改。发件人:

您必须在要创建托管上下文的线程上创建托管上下文 用过。如果使用NSOperation,请注意其init方法是在 与调用方相同的线程。因此,您不能创建 队列的init方法中队列的托管对象上下文, 否则它将与调用方的线程相关联。相反,你 应该在main(对于串行队列)或start(对于串行队列)中创建上下文 并发队列)

使用线程限制时,不应传递托管对象或 线程之间的托管对象上下文。“传递”托管对象的步骤 从一个上下文到另一个线程边界,您可以:

  • 传递其对象ID(objectID)并使用objectWithID:或existingObjectWithID:错误: 在接收托管对象上下文上。相应的托管对象必须具有 如果已保存,则无法将新插入的托管对象的ID传递给其他上下文
  • 在接收上下文上执行提取

上面的单例方法非常灵活。一种简单得多的方法是将appDelegate视为一个单例,事实就是这样。在appDelegate中创建属性,然后以下行的版本将检索您想要的属性。例如,检索moc

self.managedObjectContext = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

如果我没记错的话,您确实需要担心跨线程调用。。。我想。这意味着,虽然您可以从任何线程访问它,但不能在线程之间共享上下文。《苹果》可能是一本有用的读物。非常感谢你清晰而快速的回答。。谢谢你,Joushua也:)。。。。我只是觉得用核心数据设置创建一个单例是不好的做法。。但这让“生活”变得容易多了,所有MOC的通过都是“可怕的”:戴普,@Joshua有一个很好的观点。如果您需要执行异步调用(对于大型数据加载之类的事情),那么您需要为这些调用调整一些设计。这仍然很简单,但不像单身汉那么简单。如果有人感兴趣,我会在回答中记下这一点。我一直在同一个页面上,从来没有使用过UIManagedDocument,直到我在iTunesU上观看了最新的斯坦福课程,他们在那里使用UIManagedDocument。我对这件事的愤怒让我想到了这个问题。。。