2013-02-14 13 views
5

मैं अपने कोर डेटा स्टैक को सेट करने के बारे में थोड़ा उलझन में हूं। Appdelegate या UIManagedDocument के साझा उदाहरण का उपयोग करके, यहां वर्णित है ?: http://adevelopingstory.com/blog/2012/03/core-data-with-a-single-shared-uimanageddocument.htmlकोर डेटा: UIManagedDocument या AppDelegate कोर डेटा स्टैक सेट अप करने के लिए?

अभी मेरे पास मेरे ऐपडिलेगेट में कोर डेटा स्टैक सेटअप है और मैं व्यू कंट्रोलर के बीच अपने एमओसी को पास कर रहा हूं। लेकिन क्या UimanagedDocument में माइग्रेट करना और साझा करना आसान होगा, इसलिए मुझे हर समय एमओसी पास नहीं करना पड़ेगा? और यह भी क्योंकि इसकी नई?

उत्तर

6

UIManagedDocument डेटा (आमतौर पर फ़ाइलें) iCloud में सिंक करने के लिए प्रयोग किया जाता है। यह केवल कोर डेटा से संबंधित है।

कोर डेटा सेटअप आम तौर पर AppDelegate में किया जाता है, इसलिए आप वहां क्या कर रहे हैं के साथ कुछ भी गलत नहीं है। वास्तव में, यदि आप कोर डेटा का उपयोग करके एक नई परियोजना बनाते हैं तो यह है कि एक्सकोड टेम्पलेट इसे कैसे करेगा।

आप आमतौर पर अपने ViewController से चारों ओर ManagedObjectContext ViewController को पारित करने के लिए की जरूरत नहीं है। सिंगलटन डेटा एक्सेस लेयर बनाना बेहतर है जो आपके ऐप में कहीं भी संदर्भ प्रदान कर सकता है। ऐसे कुछ मामले हैं जहां आप व्यू कंट्रोलर के लिए एक निजी एमओसी रखना चाहते हैं, लेकिन अक्सर नहीं।

यहाँ एक सिंगलटन 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 एक बहुत ही हल्का वस्तु है, इसलिए इसे वास्तविक प्रदर्शन दंड नहीं है। हालांकि, अगर आपको अन्य धागे पर कोर डेटा सामान करने की ज़रूरत है, तो डिज़ाइन को थोड़ा बदलना होगा। Apple's docs से:

You must create the managed context on the thread on which it will be used. If you use NSOperation, note that its init method is invoked on the same thread as the caller. You must not, therefore, create a managed object context for the queue in the queue’s init method, otherwise it is associated with the caller’s thread. Instead, you should create the context in main (for a serial queue) or start (for a concurrent queue).

Using thread confinement, you should not pass managed objects or managed object contexts between threads. To “pass” a managed object from one context another across thread boundaries, you either:

  • Pass its object ID (objectID) and use objectWithID: or existingObjectWithID:error: on the receiving managed object context. The corresponding managed objects must have been saved—you cannot pass the ID of a newly-inserted managed object to another context.
  • Execute a fetch on the receiving context.
+0

यदि मुझे सही याद है, तो आपको क्रॉस थ्रेड कॉल के बारे में चिंता करने की आवश्यकता है ... मुझे लगता है। मतलब यह है कि जब आप इसे किसी भी थ्रेड से एक्सेस कर सकते हैं, तो आप धागे के बीच एक संदर्भ साझा नहीं कर सकते हैं। [कोर डेटा के साथ Concurrency] (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html) ऐप्पल से उपयोगी पढ़ा जा सकता है। – Joshua

+0

आप .. आपके स्पष्ट और त्वरित जवाब के लिए बहुत बहुत धन्यवाद आप आप के लिए बहुत धन्यवाद, Joushua:) .... मैं तो बस सोचा था कि कोर डेटा सेटअप के साथ एक सिंगलटन बनाने, खराब व्यवहार का था .. लेकिन यह "जीवन" बनाता है बहुत आसान, एमओसी से गुजरने वाले सभी "भयानक" हैं: डी – 7c9d6b001a87e497d6b96fbd4c6fdf

+0

हाँ, @ जोशुआ का एक अच्छा बिंदु है। यदि आपको एसिंक कॉल करने की आवश्यकता है (बड़े डेटा लोड जैसी चीजों के लिए) तो आपको उन कॉल के लिए डिज़ाइन को थोड़ा समायोजित करने की आवश्यकता है। यह अभी भी बहुत सीधा है, लेकिन एक सिंगलटन के रूप में सीधा नहीं है। यदि कोई दिलचस्पी लेता है तो मैं जवाब में उस पर एक नोट बनाउंगा। – memmons

1

सिंगलटन विधि ऊपर बहुत चालाक है। ऐपडिलेगेट को सिंगलटन के रूप में पेश करना एक आसान तरीका है, जो यह है। अपने ऐपडिलेगेट में गुण बनाएं, फिर निम्न पंक्ति का एक संस्करण आपको इच्छित एक पुनर्प्राप्त करेगा। उदाहरण के लिए moc

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