2011-12-30 10 views
13

के साथ आईओएस 5 में प्री-लोड कोर डेटा डेटाबेस मैं इस तरह से आने की कोशिश कर रहा हूं कि UIManagedDocument का उपयोग करते समय मैं डेटा को डेटा में प्री-लोड कर सकता हूं। मेरे प्रयास अब तक .. इस कोड का उपयोग एक "लोडर" अनुप्रयोग में दस्तावेज़ बनाने के लिए हैUIManagedDocument

NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory 
                 inDomains:NSUserDomainMask] lastObject]; 
url = [url URLByAppendingPathComponent:@"Default Database"]; 
if(![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]){ 
    [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){ 
     if(success)[self loadDataIntoDocument]; 
    }]; 
} 

और फिर 'दस्तावेज' निर्देशिका है कि संसाधन अनुभाग को सिम्युलेटर के निर्देशिका में बनाई गई है से persistentStore फ़ाइल की प्रतिलिपि मुख्य ऐप के लिए एक्सकोड में जो लोड किए गए डेटाबेस का उपयोग करेगा।

मेरी समस्या यह है कि मैं यह नहीं समझ सकता कि उस दस्तावेज़ को ऐप बंडल से कैसे कॉपी करें और इसे दस्तावेज़ के रूप में सफलतापूर्वक उपयोग करें।

मैंने ऐप बंडल से दस्तावेज़ निर्देशिका की प्रतिलिपि बनाने की कोशिश की है और इसे एक दस्तावेज़ के रूप में एक्सेस करने का प्रयास किया है जिसने UIManagedDocument त्रुटि को केवल फाइलों के पैकेज तक पहुंच सकते हैं। मैंने मुख्य ऐप में एक और नया दस्तावेज़ बनाने और उसी त्रुटि के साथ दस्तावेज़ में बनाए गए एक पर बंडल से लगातार स्टोयर की प्रतिलिपि बनाने का प्रयास किया है। और मैंने UIManagedDocument की -(BOOL)loadFromContents:ofType:error: विधि का उपयोग करने का प्रयास किया है .. मुझे यह भी यकीन नहीं है कि मुझे इसका उपयोग करना चाहिए।

क्या किसी के पास यह विचार है कि यह सामान्य रूप से कैसे किया जाता है? धन्यवाद!

उत्तर

9

मुझे नहीं लगता कि आपको आईओएस में फ़ाइलों और निर्देशिकाओं के साथ गड़बड़ करनी चाहिए।

हालांकि, आप सीधे अपने बंडल से दस्तावेज़ खोल सकते हैं। इसके लिए, आपको बस अपने लोडर ऐप में बनाए गए संपूर्ण दस्तावेज़ निर्देशिका को अपने अंतिम बंडल में कॉपी करना होगा। संरचना को सरल होना चाहिए, केवल दो निर्देशिकाओं के अंदर लगातार स्टोयर फ़ाइल के साथ।

बाद में, जब आप अपना दस्तावेज़ खोलना चाहते हैं, तो आपको दो चीजों का ख्याल रखना होगा: आपको बंडल निर्देशिका को आधार निर्देशिका के रूप में उपयोग करने की आवश्यकता है और आपको "फ़ाइल" नाम के अंत में / जोड़ने की आवश्यकता है , इसलिए UIManagedDocument जानता है कि निर्देशिका दस्तावेज़ है। कोड इस तरह दिखता है:

NSURL* url = [[NSBundle mainBundle] bundleURL]; 
url = [url URLByAppendingPathComponent:@"filename/"]; 
UIManagedDocument* doc = [[UIManagedDocument alloc] initWithFileURL:url]; 

ध्यान दें कि आप नहीं कर सकते हैं कि फाइल करने के लिए लिखने, आप अपने आवेदन बंडल के अंदर लिखने के लिए अनुमति नहीं है के रूप में। इसलिए यदि आप एक लिखने योग्य दस्तावेज़ चाहते हैं, तो आपको उस दस्तावेज़ को अपने दस्तावेज़ फ़ोल्डर में कॉपी करने की आवश्यकता है। आप आसानी से ऐसा कर सकते हैं बस किसी दूसरे स्थान पर doc सहेजकर:

[doc saveToURL:newURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){}] 

एक और बात: तुम्हें यकीन फ़ोल्डर संरचना अपने अनुप्रयोग बंडल में बनाई गई है बनाने के लिए किया है। ऐसा करने का सबसे आसान तरीका है संपूर्ण फ़ोल्डर को अपनी प्रोजेक्ट में खींचें और फिर "किसी भी जोड़े गए फ़ोल्डर के लिए फ़ोल्डर संदर्भ बनाएं" चुनें। "फ़ाइल" symbollist_en (जो वास्तव में एक बंडल/फ़ोल्डर है) के लिए यह दिखना चाहिए:
A folder reference in XCode
यदि आप ऐसा नहीं करते हैं, तो दस्तावेज़ की "सामग्री" सीधे आपके ऐप बंडल में रह जाएगी, जो जैसा कि आपने पाया, UIManagedDocument के रूप में खोला नहीं जा सकता है।

4

Shezi से जवाब बहुत मदद की, लेकिन यहाँ दूसरों की तरह: Preloaded Core Data Database in ios5 with UIManagedDocument और यहाँ: Pre load core data database coming up black with UIManagedDocument मैं समस्या थी।

सबसे पहले, सिम्युलेटर पर व्यवहार डिवाइस पर व्यवहार से काफी अलग है।यदि आप initWithURL का उपयोग करते हुए UIManagedDocument को तुरंत चालू करते हैं, जहां URL ऐप बंडल को इंगित करता है, तो आपको एक चेतावनी मिलेगी कि यह डिवाइस पर चलते समय कंसोल में केवल पढ़ने योग्य निर्देशिका है, लेकिन सिम्युलेटर पर ऐसी कोई चेतावनी दिखाई नहीं देती है। अनुमति प्रबंधन बहुत अलग लगता है और आप अलग-अलग परिणाम प्राप्त कर सकते हैं।

डॉक्स सुझाव दिया है कि migratePersistentStore:toURL:options:withType:error:[doc saveToURL:newURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){}]

के बजाय इस्तेमाल किया जाना चाहिए कि मैं इस काम करने के लिए प्राप्त करने की कोशिश एक लंबा समय बिताया लेकिन मुसीबत लगातार की दुकान में एक सूचक हो रही का एक बहुत था। हालांकि शेज़ी के समाधान के बाद मेरे ऐप ने केवल पढ़ने के लिए ऑपरेशन के लिए ठीक काम किया, फिर भी लगातार स्टोर समन्वयक ने मुझे लगातार स्टोर के लिए एक शून्य सूचक देने पर रखा। ऐसा तब हुआ जब मैंने – persistentStores दोनों (जो एक खाली सरणी लौटा दी) और – persistentStoreForURL: यदि कोई यह समझा सकता है कि ऐसा क्यों हुआ, तो मुझे दिलचस्पी होगी। कष्टप्रद बात यह थी कि यह कभी-कभी सिम्युलेटर पर काम करेगा, लेकिन जब मैंने डिवाइस पर परीक्षण किया, तो यह असफल रहा।

अंत में, मैंने चीजों को बदल दिया और UIManagedDocument को तुरंत चालू करने से पहले बंडल फ़ोल्डर को पहले दस्तावेज़ निर्देशिका में कॉपी किया। ऐसा लगता है कि चाल चल रही है। कोड यहाँ है। यह मानता है कि आपका UIManagedDocument कक्षा की एक संपत्ति है। मैंने इसे प्रारंभिक दृश्य नियंत्रक के दृश्यपिल्पर विधि में रखा है। याद रखें कि यदि आप एक मौजूदा निरंतर स्टोर वाले यूआरएल का उपयोग करते हैं तो आपको दस्तावेज़ खोलने की जरूरत है।

if (!self.yourUIManagedDocument) { 
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"yourUIManagedDocument"]; 
    NSString *documentsFolderPath = [documentsDirectory stringByAppendingPathComponent:@"yourUIManagedDocument"]; 

    NSURL *documentsUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
    documentsUrl = [documentsUrl URLByAppendingPathComponent:@"yourUIManagedDocument"]; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:documentsFolderPath]) { 
     NSError *error = nil; 

     if([[NSFileManager defaultManager] copyItemAtPath:bundlePath 
                toPath:documentsFolderPath 
                error:&error]) { 
      self.yourUIManagedDocument = [[UIManagedDocument alloc] initWithFileURL:documentsUrl]; 
      [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
      }]; 
     } else { 
      NSLog(@"%@", error); 
     } 
    } else { 
     self.yourUIManagedDocument = [[UIManagedDocument alloc] initWithFileURL:documentsUrl]; 
     [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
     }]; 
    } 
} else if (self.yourUIManagedDocument.documentState == UIDocumentStateClosed) { 
    //Document is closed. Need to open it 
    [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
    }]; 
} 
बेशक

, ऊपर मानता है कि आप पहले से ही सिम्युलेटर का उपयोग कर डेटाबेस उत्पन्न होते हैं और ठीक वैसी Shezi वर्णित में एप्लिकेशन बंडल में निर्देशिका की नकल की है। कोड को सुधारने के लिए कोई टिप्पणी या सुझाव स्वागत है। मैं अभी भी सीख रहा हूँ।

+0

क्या मैं कर रहा हूँ निम्न निर्देशिका (दस्तावेज़/AppDatabase/StoreContent) दस्तावेजों निर्देशिका में पैदा कर रही है और केवल StoreContent फ़ोल्डर में persistentStore फ़ाइल मुकाबला। यह मेरे लिए काम कर रहा है। क्या आपको लगता है कि मुझे कोई समस्या होगी? – tomidelucca

0

शेज़ी की विधि मेरे लिए काम करती प्रतीत होती है, केवल एक चीज जिसे मैं जोड़ना चाहता हूं वह है "फाइल" का अर्थ इस मामले में symbolist_en है। यह मेरे जैसे नए डेवलपर्स के लिए थोड़ा उलझन में हो सकता है (मैं लगातार स्टोर/डाल रहा था)।

+0

यह इंगित करने के लिए धन्यवाद, मैंने इसे प्रतिबिंबित करने के लिए अपना उत्तर संपादित कर दिया है। – shezi

0

शेज़ी द्वारा दिए गए उत्तर में बहुत मदद मिली। लेकिन यह काम नहीं किया है। मैंने दस्तावेज़ निर्देशिका को एक्सकोड में गिरा दिया लेकिन इसे बंडल से दस्तावेज़ निर्देशिका में कॉपी नहीं किया जा रहा था। फिर मैंने प्री-लोड के संबंध में मैकबेब के question पर ठोकर खाई। मैंने अपने दृष्टिकोण की कोशिश की जिसमें बंडल में लगातार स्टोयर फ़ाइल शामिल है। फिर दस्तावेज़ के फ़ोल्डर के तहत आवश्यक दस्तावेज़ नाम निर्देशिका बनाना और फिर उस पथ पर लगातार स्टोर की प्रतिलिपि बनाना।

चेक टिप्पणी "की नकल बंडल से"

साथ कोड मैं दस्तावेज़ से निपटने के लिए स्थिर वर्ग का इस्तेमाल किया है।

+(DocumentHandler *) sharedDocumentHandler { 
    static DocumentHandler *mySharedDocumentHandler = nil; 
    static dispatch_once_t once; 
    dispatch_once(&once, ^{ 
     mySharedDocumentHandler = [[self alloc] init]; 
    }); 
    return mySharedDocumentHandler; 
} 

- (id)init { 
    self = [super init]; 
    if (self) { 
     NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
     url = [url URLByAppendingPathComponent:@"YourDocumentName"]; 
     self.sharedDocument = [[MyUIManagedDocument alloc] initWithFileURL:url]; 
    } 
    return self; 
} 
- (void)performWithDocument:(OnDocumentReady)onDocumentReady 
{ 
    void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success) { 
     if(success) { 
      onDocumentReady(self.sharedDocument); 
     } else { 
      NSLog(@"Error occured while creating or opening the database"); 
     } 
    }; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.sharedDocument.fileURL path]]) { 
     NSError *error = nil; 

     // COPY FROM BUNDLE 

     NSFileManager *fileManager = [NSFileManager defaultManager]; 

     NSString *DB = [[self.sharedDocument.fileURL path] stringByAppendingPathComponent:@"StoreContent"]; 

     [fileManager createDirectoryAtPath:DB withIntermediateDirectories:YES attributes:nil error:&error]; 

     NSLog(@"create directory error: %@",error); 

     DB = [DB stringByAppendingPathComponent:@"persistentStore"]; 

     NSString *shippedDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"persistentStore"]; 

     NSLog(@"%d",[fileManager fileExistsAtPath:shippedDB]); 

     [fileManager copyItemAtPath:shippedDB toPath:DB error:&error]; 

     NSLog(@"Copy error %@",error);   
    } 

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.sharedDocument.fileURL path]]) { 
     //Create documents [This is required while creating database first time] 
     [self.sharedDocument saveToURL:self.sharedDocument.fileURL 
       forSaveOperation:UIDocumentSaveForCreating 
       completionHandler:OnDocumentDidLoad]; 
    } else if (self.sharedDocument.documentState == UIDocumentStateClosed) { 
     [self.sharedDocument openWithCompletionHandler:OnDocumentDidLoad]; 
    } else if (self.sharedDocument.documentState == UIDocumentStateNormal) { 
     OnDocumentDidLoad(YES); 
    } 
} 
संबंधित मुद्दे