2011-12-30 71 views
13

我試圖想出一種方法,可以在使用UIManagedDocument時將數據預加載到核心數據中。我嘗試迄今使用這個代碼,以使文檔中的「裝載機」應用..在iOS 5中預加載核心數據數據庫並使用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文件從在仿真器的目錄中創建的資源節中的「文檔」目錄複製在Xcode的主要應用程序將使用加載的數據庫。

我的問題是,我不知道如何從應用程序包中複製該文檔併成功地將其用作文檔。

我已經嘗試從應用程序包中原樣複製文檔目錄並試圖訪問它作爲文檔,它給出了UIManagedDocument只能訪問一個文件包的錯誤。 我已經嘗試在主應用程序中創建另一個新文檔,並將包中的persistentStore複製到具有相同錯誤的文檔中創建的文檔中。 我試過使用UIManagedDocument-(BOOL)loadFromContents:ofType:error:方法..我甚至不確定這是我應該使用的。

有沒有人有一個想法,如何這通常完成?謝謝!

回答

9

我不認爲你應該在iOS自己的文件和目錄。

但是,您可以直接從您的包中打開文檔。爲此,您只需將您在Loader應用程序中創建的整個文檔目錄複製到最終捆綁包中。該結構應該很簡單,只需要兩個帶有persistentStore文件的目錄。

之後,當您要打開文檔時,需要注意以下兩點:需要使用捆綁目錄作爲基礎目錄,並且需要在「文件」名稱末尾添加/ ,所以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){}]

我花了很長時間試圖讓這個工作,但有很多的麻煩的指針持久性存儲。即使我的應用程序在遵循Shezi的解決方案後仍能正常工作,持久存儲協調器仍然持續爲我提供持久存儲的空指針。發生這種情況時,我試圖– persistentStores(它返回一個空陣列)和 – persistentStoreForURL:如果任何人都可以解釋爲什麼發生這種情況,我會感興趣。令人討厭的是它有時會在模擬器上工作,但是當我在設備上測試時,它失敗了。

最後,我改變了事情,並在實例化UIManagedDocument之前先將包文件夾複製到文檔目錄中。這似乎已經成功了。這是代碼。它假定你的UIManagedDocument是該類的一個屬性。我把它放在初始視圖控制器的viewWillAppear方法中。請記住,如果使用包含現有持久性存儲的URL進行實例化,則需要打開該文檔。

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

我在做什麼是在文檔目錄中創建以下目錄(Documents/AppDatabase/StoreContent),並且只處理StoreContent文件夾中的persistentStore文件。這對我有用。你認爲我會有什麼問題嗎? – tomidelucca 2012-09-04 00:53:20

0

shezi的方法似乎爲我工作,我想補充的唯一的東西是「文件」在這種情況下意味着symbolist_en。對於像我這樣的新開發人員來說,這可能有點令人困惑(我正在將persistentStore /)。

+0

感謝您指出這一點,我編輯了我的答案來反映這一點。 – shezi 2013-01-12 12:33:56

0

Shezi的答案幫了很大忙。但它沒有按原樣工作。我在xcode中刪除了文檔目錄,但沒有從bundle複製到Documents目錄。然後我偶然發現了關於預加載的macbeb的question。我嘗試了他的方法,其中涉及到包含persistentStore文件。然後在Document的文件夾下創建所需的文檔名稱目錄,然後將persistentStore複製到該路徑。

檢查與評論「COPY從內容集中」

的代碼,我使用的靜態類文檔處理。

+(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); 
    } 
}