2010-02-26 12 views
5

मैं एक ऐप के नए संस्करण के साथ एक अद्यतन SQLite डेटाबेस शामिल करना चाहता हूं। मेरा ऐप डेटाबेस फ़ाइल को स्टार्टअप पर दस्तावेज़ निर्देशिका में कॉपी करता है। इस तरह के संस्करण (कोर डेटा का उपयोग करने के अलावा) करने का सबसे अच्छा तरीका क्या है?SQLite, iPhone और संस्करण

मुझे लगता है कि या तो SQLite फ़ाइल में एक विशेष 'संस्करण' तालिका या संस्करण संख्या के साथ एक छोटी पाठ फ़ाइल जाने का तरीका है, लेकिन मैं अन्य लोगों की राय प्राप्त करना चाहता हूं।

उत्तर

0

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

फ़ाइल टाइमस्टैम्प का उपयोग करना काम नहीं करता है, क्योंकि ऐप समीक्षा समय विंडो में ऐप डाउनलोड करने की संभावना है और बंडल में से एक की तुलना में एक नए टाइमस्टैम्प के साथ एक प्रतिलिपि डेटाबेस के साथ समाप्त हो रहा है।

0

मैं जिस तरह से करता हूं वह फिलास्टैम्प देखकर होता है। यदि .app बंडल में SQLite DB फ़ाइल की संशोधन तिथि स्थानीय दस्तावेज़ निर्देशिका में से एक से अधिक हालिया है, तो मैं एक .app बंडल से एक की प्रतिलिपि बनाता हूं ... यहां मैं उपयोग किया गया कोड है।

sqlite3 *dbh;   // Underlying database handle 
NSString *name;   // Database name (this is the basename part, without the extension) 
NSString *pathBundle; // Path to SQLite DB in the .app folder 
NSString *pathLocal; // Path to SQLite DB in the documents folder on the device 

- (BOOL)automaticallyCopyDatabase {        // Automatically copy DB from .app bundle to device document folder if needed 
    ES_CHECK(!dbh, NO, @"Can't autoCopy an already open DB") 
    ES_CHECK(name!=nil, NO, @"No DB name specified") 
    ES_CHECK(pathBundle!=nil, NO, @"No .app bundle path found, this is a cache DB") 
    ES_CHECK(pathLocal!=nil, NO, @"No local document path found, this is a read-only DB") 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSDictionary *localAttr = [fileManager fileAttributesAtPath:pathLocal traverseLink:YES]; 
    BOOL needsCopy = NO; 
    if (localAttr == nil) { 
     needsCopy = YES; 
    } else { 
     NSDate *localDate; 
     NSDate *appDBDate; 
     if (localDate = [localAttr objectForKey:NSFileModificationDate]) { 
      ES_CHECK([fileManager fileExistsAtPath:pathBundle], NO, @"Internal error: file '%@' does not exist in .app bundle", pathBundle) 
      NSDictionary *appDBAttr = [fileManager fileAttributesAtPath:pathBundle traverseLink:YES]; 
      ES_CHECK(appDBAttr!=nil, NO, @"Internal error: can't get attributes for '%@'", pathBundle) 
      appDBDate = [appDBAttr objectForKey:NSFileModificationDate]; 
      ES_CHECK(appDBDate!=nil, NO, @"Internal error: can't get last modification date for '%@'", pathBundle) 
      needsCopy = [appDBDate compare:localDate] == NSOrderedDescending; 
     } else { 
      needsCopy = YES; 
     } 
    } 
    if (needsCopy) { 
     NSError *error; 
     BOOL success; 
     if (localAttr != nil) { 
      success = [fileManager removeItemAtPath:pathLocal error:&error]; 
      ES_CHECK(success, NO, @"Can't delete file '%@'" ,pathLocal) 
     } 
     success = [fileManager copyItemAtPath:pathBundle toPath:pathLocal error:&error]; 
     ES_CHECK(success, NO, @"Can't copy database '%@' to '%@': %@", pathBundle, pathLocal, [error localizedDescription]) 
     ES_TRACE(@"Copied DB '%@' to '%@'", pathBundle, pathLocal) 
     return success; 
    } 
    return YES; 
} 

ES_CHECK बातें सिर्फ मैक्रोज़ को रिलीज़ मोड में कुछ भी नहीं करने के लिए विस्तृत करें और डिबग मोड में एक अपवाद बढ़ा रहे हैं ... वे इस तरह दिखेगा:

#if ES_DEBUG 
#define ES_ASSERT(cond) assert(cond); 
#define ES_LOG(msg...) NSLog(msg); 
#define ES_TRACE(msg...) NSLog(msg); 
#else 
#define ES_ASSERT(cond) 
#define ES_LOG(msg...) 
#define ES_TRACE(msg...) 
#endif 
#define ES_CHECK(cond, ret, msg...) if (!(cond)) { ES_LOG(msg) ES_ASSERT(cond) return (ret); }  // Check with specified return value (when condition fails) 
+0

वह 'ES_CHECK' मैक्रो दिलचस्प है ... डीबग मोड में, आप एक दावे के साथ विफल हो जाते हैं, लेकिन रिलीज मोड में आप एक त्रुटि कोड लौटाते हैं, इसलिए वास्तविक कोड डीबग और मोड को रिलीज़ करने में जंगली रूप से भिन्न होता है। तो आप केवल यह जांच सकते हैं कि कॉलिंग कोड सभी डीबगिंग को चालू करके लौटाए गए त्रुटि कोड को संभाल सकता है? –

+0

हां। लेकिन चेक में से कोई भी असफल नहीं है, यही विचार है। यदि वे कभी भी उत्पादन में असफल होते हैं, तो वे दुर्घटनाग्रस्त होने के बजाय एक समझदार मूल्य लौटकर नियमित शॉर्ट कट करते हैं ... –

4

एक विशेष तालिका के लिए कोई ज़रूरत नहीं। SQLite के लिए एक प्रज्ञा है, जिसे user_version कहा जाता है। SQLite किसी भी चीज़ के लिए इस मान का उपयोग नहीं करता है, यह पूरी तरह से एप्लिकेशन के लिए छोड़ दिया गया है।

#pragma user_version; 

संस्करण सेट करने के लिए:

संस्करण को पढ़ने के लिए कुछ तकनीक की कोशिश के बाद

#pragma user_version=1; 
+0

प्रोग्रामेटिक रूप से sqlite में user_version कैसे सेट करें? मैं db से user_version पढ़ सकता हूं लेकिन किसी कारण से अद्यतन विफल रहता है ... !! कोई मदद ? – Unicorn

+0

यह तब होता है जब मैं स्मृति से काम करता हूं। :) उत्तर तय। –