2013-10-07 11 views
13

मेरे पास एक NSDocument आधारित एप्लिकेशन है जो फ़ाइल डेटा को सहेजने और लोड करने के लिए फ़ाइलवापर का उपयोग करता है। दस्तावेज़ में सभी प्रकार के संसाधन हो सकते हैं, इसलिए मैं सबकुछ स्मृति में लोड नहीं करना चाहता हूं। मैं कुछ मौलिक रूप से गलत कर रहा हूं, लेकिन जैसे ही मैं एक (आंतरिक) फ़ाइल बदलता हूं और फिर सहेजता हूं, मैं किसी भी फाइल को नहीं पढ़ सकता जो स्मृति में लोड नहीं किया गया है।NSFileWrapper, आलसी लोडिंग और बचत

मैंने इस व्यवहार को पुन: उत्पन्न करने के लिए प्रासंगिक कोड को एक अलग प्रोजेक्ट में अलग कर दिया है, और मुझे एक ही परिणाम मिलते हैं। मूल प्रवाह यह है:

  • मैं डिस्क से एक मौजूदा दस्तावेज़ लोड करता हूं। मुख्य फ़ाइलवापर एक निर्देशिका फ़ाइलवापर है (मैं उस मुख्य पर कॉल करूंगा) जिसमें दो अन्य फ़ाइलवापर (उप 1 और उप 2) शामिल हैं। दो आंतरिक फ़ाइलवापर इस बिंदु पर लोड नहीं हैं।
  • जब उपयोगकर्ता उप 1 संपादित करना चाहता है, तो यह डिस्क से लोड होता है।
  • उपयोगकर्ता उपयोगकर्ता अन्य फ़ाइल (sub2) संपादित करने के लिए चाहता है दस्तावेज
  • की बचत होती है, यह लोड नहीं कर सकता। त्रुटि है कि प्रतीत होता है:

    -[NSFileWrapper regularFileContents] tried to read the file wrapper's contents lazily but an error occurred: The file couldn’t be opened because it doesn’t exist. 
    

यहाँ मेरी परियोजना में प्रासंगिक कोड है:

इस कोड को इस सार में पढ़ने के लिए आसान हो सकता है: https://gist.github.com/bob-codingdutchmen/6869871

#define FileName01 @"testfile1.txt" 
#define FileName02 @"testfile2.txt" 

/** 
* Only called when initializing a NEW document 
*/ 
-(id)initWithType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    self = [self init]; 
    if (self) { 
     self.myWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil]; 

     NSLog(@"Initializing new document..."); 

     NSString *testString1 = @"Lorem ipsum first sub file"; 
     NSString *testString2 = @"This is the second sub file with completely unrelated contents"; 

     NSFileWrapper *w1 = [[NSFileWrapper alloc] initRegularFileWithContents:[testString1 dataUsingEncoding:NSUTF8StringEncoding]]; 
     NSFileWrapper *w2 = [[NSFileWrapper alloc] initRegularFileWithContents:[testString2 dataUsingEncoding:NSUTF8StringEncoding]]; 

     w1.preferredFilename = FileName01; 
     w2.preferredFilename = FileName02; 

     [self.myWrapper addFileWrapper:w1]; 
     [self.myWrapper addFileWrapper:w2]; 

    } 
    return self; 
} 

-(NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 

    // This obviously wouldn't happen here normally, but it illustrates 
    // how the contents of the first file would be replaced 
    NSFileWrapper *w1 = [self.myWrapper.fileWrappers objectForKey:FileName01]; 
    [self.myWrapper removeFileWrapper:w1]; 

    NSFileWrapper *new1 = [[NSFileWrapper alloc] initRegularFileWithContents:[@"New file contents" dataUsingEncoding:NSUTF8StringEncoding]]; 
    new1.preferredFilename = FileName01; 

    [self.myWrapper addFileWrapper:new1]; 

    return self.myWrapper; 
} 

-(BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    self.myWrapper = fileWrapper; 
    return YES; 
} 

- (IBAction)button1Pressed:(id)sender { 
    // Read from file1 and show result in field1 
    NSFileWrapper *w1 = [[self.myWrapper fileWrappers] objectForKey:FileName01]; 
    NSString *string1 = [[NSString alloc] initWithData:w1.regularFileContents encoding:NSUTF8StringEncoding]; 
    [self.field1 setStringValue:string1]; 
} 

- (IBAction)button2Pressed:(id)sender { 
    // Read from file2 and show result in field2 
    NSFileWrapper *w2 = [[self.myWrapper fileWrappers] objectForKey:FileName02]; 
    NSString *string2 = [[NSString alloc] initWithData:w2.regularFileContents encoding:NSUTF8StringEncoding]; 
    [self.field2 setStringValue:string2]; 
} 

नीचे दो विधियां केवल यूआई को अपडेट करने के लिए हैं, इसलिए मैं देख सकता हूं कि क्या होता है।

  • फ़ाइल की सामग्री को बदलने के लिए, मैं मौजूदा फ़ाइल को हटा देता हूं और एक नया जोड़ता हूं। यह एकमात्र तरीका है जिसे मैंने फ़ाइल की सामग्री को बदलने के लिए पाया है, और जिस तरह से मैंने इसे अन्य SO उत्तरों में देखा है।

  • जब एक दस्तावेज़ डिस्क से भरी हुई है, मैं (ऊपर कोड में myWrapper कहा जाता है)

एप्पल डॉक्स का कहना है कि NSFileWrapper आलसी लोड हो रहा है और समर्थन करता है, तो मैं उपयोग कर सकते हैं चारों ओर fileWrapper रखने वृद्धिशील बचत, इसलिए मुझे लगता है कि मेरे कोड में कुछ मौलिक दोष है जिसे मैं नहीं देख सकता।

+0

क्या आपका दस्तावेज़ वर्जनिंग का समर्थन करता है? –

+0

मुझे यकीन नहीं है, इसलिए मुझे नहीं लगता :) मैंने इसका समर्थन करने के लिए कुछ भी नहीं किया है। क्या यह कुछ बदल जाएगा? मैं उस बाद में –

+1

देखूँगा क्योंकि मैं एक NSDocument सेटअप का उपयोग कर रहा हूं, मैं संस्करण का समर्थन कर रहा था। मैंने इसे बंद करने का प्रयास किया है, लेकिन परिणाम एक ही –

उत्तर

1

एक NSFileWrapper अनिवार्य रूप से एक यूनिक्स फ़ाइल नोड के चारों ओर एक रैपर है। अगर फ़ाइल स्थानांतरित हो जाती है तो रैपर वैध रहता है।

समस्या यह है कि समस्या यह है कि सहेजने के दौरान एक नया फ़ाइल रैपर बनाना एक नया फ़ोल्डर है। और सिस्टम आपके पिछले रैपर को उप 2 सहित हटा देता है।

जो आप चाहते हैं उसे प्राप्त करने के लिए आपको वृद्धिशील बचत में परिवर्तन करने की आवश्यकता है, यानी केवल बदले गए हिस्सों को ही जगह में सहेजना है। NSDocument में "जगह में सहेजें" देखें।

1

अपने -fileWrapperOfType:error: विधि में, एक नया फ़ाइल रैपर बनाने का प्रयास करें जिसमें बदले गए सदस्यों के लिए नई सामग्री है और अपरिवर्तित सदस्यों के लिए पुरानी फ़ाइल रैपर का संदर्भ लें।

0

addFileWrapper लिए दस्तावेज़ीकरण का अनुसरण: यह करने के लिए आप एक बच्चे (उपनिर्देशिका) जोड़ने के लिए, इसका मतलब है

निर्देशिका/

  1. addfileWrapper: fileName1 निर्देशिका/fileName1/

  2. addfileWrapper: fileName2 निर्देशिका/फ़ाइल नाम 1/फ़ाइल नाम 2। वह फ़ाइल मौजूद नहीं है। preferredFilename: बजाय

आप addRegularFileWithContents उपयोग करना होगा।

संबंधित मुद्दे