2010-08-30 35 views
0

我正在寫一個應用程序連接到數據庫來獲取數據。由於取數很昂貴且數據通常不變,因此我使用CoreData來緩存結果,以便我可以快速進行本地查詢。如何獲取核心數據以使用我自己的NSManagedObjectID URI方案?

從數據庫中,對於每種類型,都有一個保證爲唯一的字符串屬性。實際上,數據庫有一個URI方案,它是每個項目的唯一地址。

的URL方案是沿着線非常基本的:

ngaobject:// <server_license_id>/<類型>/<標識符>

我想能夠在CoreData中也使用它。我做了從CoreData商店獲取單個項目的方法:

-(NSFetchRequest*)fetchRequestForType:(NSString*)typeName identifier:(NSString*)identifier 
{ 
    NSFetchRequest * fetchRequest = [self fetchRequestForType:typeName]; 

    [fetchRequest setFetchLimit:1]; 

    NSString * identifierProperty = [self identifierPropertyNameForObjectType:typeName]; 
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%K == %@", identifierProperty, identifier]; 
    [fetchRequest setPredicate:predicate]; 

    return fetchRequest; 
} 

-(NGAObject*)objectWithType:(NSString*)typeName 
identifier:(NSString*)identifier 
    { 
     // First try to retrieve it from the cache 

    NSAssert1((identifier != nil), @"Request to create nil-name object of type %@", typeName); 

    NSFetchRequest * fetchRequest = [self fetchRequestForType:typeName identifier:identifier]; 

    if (!fetchRequest) 
     return nil; 

    NSError * error = nil; 
    NSArray * fetchResults = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error]; 

    if (!fetchResults) 
    { 
     NSLog(@"%@", error); 
     [NSApp presentError:error]; 
     return nil; 
    } 

    if ([fetchResults count]) 
     return [fetchResults objectAtIndex:0]; 

    return nil; 
} 

當我從服務器獲取一個項目,我想先得到在緩存對它的引用,如果它的存在,更新它。如果不是,請創建一個新的。

由於我從服務器回收了數千個對象,因此對我知道唯一ID的單個對象執行抓取操作會使我的機器抓取。

相反,我正在做的是預先加載一個類型的所有對象,然後創建一個標識符 - >對象的字典,然後通過在字典中運行它來處理該類型的數千個對象。這工作正常,但很尷尬。

難道我不能寫一個方法,它需要類型/標識符組合,並從CoreData中獲取單個對象,而無需執行冗長的獲取請求嗎?

似乎有一個解決方案,如果我可以讓CoreData使用我自己的URI規範。然後,我可以在持久性商店協調員上撥打 - (NSManagedObjectID*)managedObjectIDForURIRepresentation:(NSURL*)url

所以,問題是,我怎樣才能讓CoreData使用我的URI方案?我如何讓CoreData使用我自己的唯一標識符?

回答

0

在CoreData設計器中,您用於唯一ID查找標記爲「索引」的所有字段?如果已經完成,CoreData提取不應該很長...

+0

不,事實並非如此。這是一個很好的建議,我會試一試。只是爲了這個問題,是否有辦法完成我已經佈置的東西? – 2010-08-30 17:39:42

+0

不確定,這裏的另一個問題似乎不是建議。一般來說,如果你發現自己試圖破解CoreData工作原理的內容,那麼你可能做錯了什麼。在這種情況下,我非常肯定最好的解決方案就是使用表索引,這將是建議的CoreData方法來做到這一點(實際上這將適用於任何RDBMS) – glenc 2010-09-03 19:24:24

1

您不能使Core Data使用自定義URI方案。 URI方案被硬編碼到核心數據中,使得URI可以被解碼以在特定硬件上的特定應用中的特定商店中查找特定數據。如果URI是可定製的,則該系統會崩潰。

奇異地提取對象是什麼在殺死你。相反,您需要批量提取customID與服務器提供的所有對象。以最簡單的方法是使用IN謂詞操作:

NSArray *customIDs=//... array of customIDs provided by server 
NSPredicate *p; 
p=[NSPredicate predicateWithFormat: @"customIdAtrribute IN %@", customIDs]; 

這將返回你可以忽略所有現有的對象。

或者,你可以

  1. 做一個被取出的propertiesToFetch設置爲customID屬性獲取上只是customID財產。
  2. 將提取結果類型設置爲字典。
  3. 使用上面的謂詞。
  4. 您將獲得一個由customID作爲每個值返回的一個鍵字典數組。
  5. 將字典轉換爲一個值數組例如cachedIDs
  6. 將上面的customIDs轉換爲可變數組。
  7. 篩選使用謂詞customIDs陣列,@"NOT (SELF IN %@)", cachedIDs"
  8. 將過濾customIDs陣列現在將只包含的自訂值在覈心數據不被緩存。
  9. 您只能爲新ID創建管理對象。

(這是你如何使用過濾器斷言,如果你是unfamilar它。)

NSMutableArray *f=[NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",nil]; 
NSArray *g=[NSArray arrayWithObjects:@"5",@"6",nil]; 
[f filterUsingPredicate:[NSPredicate predicateWithFormat:@"NOT (SELF IN %@)",g]]; 
NSLog(@"f=%@",f); 

...它輸出:

f=(
    1, 
    2, 
    3, 
    4 
)