2011-11-15 86 views
2

我有一個CoreData中的整數值的列。在從中檢索結果時,我希望列值減去一個數字。CoreData數學函數

喜歡的東西:columnValue - someNumber(這個數字由用戶輸入)

我知道我可能要使用NSPredicate這一點,但我不知道是否有它的功能和語法。

現在我有的替代方法是迭代所有列值並用'someNumber'進行減法。但我認爲應該有一個更好和有效的方式來做到這一點。


編輯:代碼從@ salo.dm的回答

 - (NSDictionary *)myFetchResults { 
    //Predicate works fine 
      NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:pred1, pred2, nil]]; 

      /*Sort Descroptor - Sorting by 4 columns*/ 
      NSSortDescriptor *sortDesc1 = [NSSortDescriptor sortDescriptorWithKey:@"Column1" ascending:YES]; 
      NSSortDescriptor *sortDesc2 = [NSSortDescriptor sortDescriptorWithKey:@"Column2" ascending:YES]; 
      NSSortDescriptor *sortDesc3 = [NSSortDescriptor sortDescriptorWithKey:@"Column3" ascending:YES]; 
      NSSortDescriptor *sortDesc4 = [NSSortDescriptor sortDescriptorWithKey:@"Column4" ascending:YES]; 

      /*Get Data*/ 
      MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 
      NSManagedObjectContext *context = [appDelegate managedObjectContext]; 

      NSEntityDescription *entity = [NSEntityDescription entityForName:@"TableName" inManagedObjectContext:context]; 
      NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
      [fetchRequest setEntity:entity]; 
      [fetchRequest setPredicate:predicate]; 
      [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDesc1, sortDesc2, sortDesc3, sortDesc4, nil]]; 

      NSArray *listData = [context executeFetchRequest:fetchRequest error:nil]; 


      /*Create subtract expression*/ 
      NSExpressionDescription *subExp1 = [[NSExpressionDescription alloc] init]; 
     [subExpLatitude setName:@"subtraction1"]; 
     [subExpLatitude setExpression:[NSExpression expressionForFunction:@"from:subtract:" 
                   arguments:[NSArray arrayWithObjects: 
                      [NSExpression expressionForKeyPath:@"Column3"], 
                      [NSExpression expressionForConstantValue:[NSNumber numberWithDouble:someNumber1]], 
                      nil]]]; 
      [subExp1 setExpressionResultType:NSDoubleAttributeType]; 

      NSExpressionDescription *subExp2 = [[NSExpressionDescription alloc] init]; 
     [subExpLongitude setName:@"subtraction2"]; 
     [subExpLongitude setExpression:[NSExpression expressionForFunction:@"from:subtract:" 
                    arguments:[NSArray arrayWithObjects: 
                       [NSExpression expressionForKeyPath:@"Column4"], 
                       [NSExpression expressionForConstantValue:[NSNumber numberWithDouble:someNumber2]], 
                       nil]]]; 
      [subExp2 setExpressionResultType:NSDoubleAttributeType]; 

      /*Get difference data*/ 
      [fetchRequest setResultType:NSDictionaryResultType]; 
      [fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:subExp1, subExp2, nil]]; 

      NSArray *listDifference = [context executeFetchRequest:fetchRequest error:nil]; 

      NSLog(@"Subtraction 1: %@", [[listDifference objectAtIndex:0] objectForKey:@"subtraction1"]); 
      NSLog(@"Subtraction 2: %@", [[listDifference objectAtIndex:0] objectForKey:@"subtraction2"]); 

      NSMutableDictionary *dictResult; 
      [dictResult setObject:listData forKey:@"Data"] 
      [dictResult setObject:listDifference forKey:@"Difference"] 

     return dictResult; 
} 

編輯:獲取coredata對象

這是行不通的。

​​

只好將其更改爲下面得到它的工作(假設這是正確的方式)

NSExpressionDescription *expEntity = [[NSExpressionDescription alloc] init]; 
    [expEntity setName:@"TableNameEntity"]; 
    [expEntity setExpression:[NSExpression expressionForEvaluatedObject]]; 
    [expEntity setExpressionResultType:NSObjectIDAttributeType]; 

我加expEntity到setPropertiesToFetch列表。現在我在字典中得到兩個值。

{ 
    TableNameEntity = "0x5e22120 <x-coredata://1A659A52-9321-4ACD-992B-04F20E7BDCED/TableNameEntity/p1640>"; 
    subtractionValue = "-24.13"; 
} 

當我嘗試從字典中檢索並訪問TableNameEntity時,應用程序崩潰。

TableNameEntity *tableEntity = (TableNameEntity *)[dict objectForKey:@"TableNameEntity"]; 
tableEntity.column1 //This is not the exact code. But this operation crashes with error 

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSObjectID_48_0 column1]: unrecognized selector sent to instance 0x5e22120' 

在這裏,如果你發現,關鍵TableNameEntity值包含在引號中,所以我想它返回一個字符串。

看看你能糾正我做錯了什麼。


我已經嘗試了一種替代方法來獲取字典中的列值。這是(這工作正常)。但我想它不是一個好方法。

[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:subExp1, @"column1", @"column2", ... @"columnN" nil]]; 

回答

4

你可以使計算在提取請求如下:

- (NSArray *)myFetchResults 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    request.entity = [NSEntityDescription entityForName:@"myEntity" inManagedObjectContext:myContext]; 

    request.resultType = NSDictionaryResultType; 

    NSExpressionDescription *subExDescr = [[NSExpressionDescription alloc] init]; 
    [subExDescr setName:@"subtraction"]; 
    [subExDescr setExpression:[NSExpression expressionForFunction:@"subtract:from:" 
                  arguments:[NSArray arrayWithObjects: 
                    [NSExpression expressionForConstantValue:[NSNumber numberWithInt:someNumber]], 
                    [NSExpression expressionForKeyPath:@"myAttribute"], 
                    nil]]]; 
    [subExDescr setExpressionResultType:NSInteger64AttributeType]; 

    request.propertiesToFetch = [NSArray arrayWithObject:subExDescr, nil]; 

    NSError *err = nil; 
    NSArray *results = [self.moContext executeFetchRequest:request error:&err]; 
    [request release]; 
    [err release]; 

    return results; 
} 

取指令的結果將是字典的陣列。您可以按如下方式訪問列中第n個值的結果:

NSArray *results = [self myFetchResults]; 
NSDictionary *nthDict = [results objectAtIndex:n]; 
NSInteger nthValue = [nthDict objectForKey:@"subtraction"]; 

請注意,此代碼未經測試。因爲我相信它會對列中的所有項目進行操作。如果您只想操作所選項目,則可以添加謂詞以選擇要操作的項目。

您也可以查閱NSExpression的文檔並構建各種不同的操作。這個類有點密集,但Apple文檔有一些代碼片斷,有助於理解如何使用它。我希望上面的例子說明了如何將它整合到一個獲取請求中。

編輯:CORRECTION

的實體,當然,在獲取請求中指定。我最初已經把它留下了,但現在已經糾正了這些代碼。


編輯:迴應置評

我不知道我知道你要問什麼,但是這可能是它。您可以創建表達式描述如下:

NSExpressionDescription *expLatitude = [[NSExpressionDescription alloc] init]; 
[expLatitude setName:@"latitude"]; 
[expLatitude setExpression:[NSExpression expressionForKeyPath:@"Column3"]]; 
[expLatitude setExpressionResultType:NSDoubleAttributeType]; 

NSExpressionDescription *expEntity = [[NSExpressionDescription alloc] init]; 
[expEntity setName:@"TableNameEntity"]; 
[expEntity setExpression:[NSExpression expressionForKeyPath:@"objectID"]]; 
[expEntity setExpressionResultType:NSObjectIDAttributeType];} 

然後,將它們添加到propertiesToFetch陣列,作爲兩個對象。提取結果中的每個字典現在都將具有緯度,由同一緯度產生的相減,以及包含該緯度的實體的相應對象ID。字典將根據您的排序描述符在結果數組中排序。 (我沒有嘗試objectID表達式,但我認爲它應該可以正常工作)。

基本上,您的結果按照與傳統的獲取請求具有相同的謂詞和相同的排序描述符的順序排列,對於具有默認結果類型NSManagedObjectResultType的提取請求。

我希望這能回答你的問題。如果不是,請不要猶豫,再問一次。但是,我可能需要一段時間才能回答,因爲現在是我的睡眠時間。


編輯:應對上找到正確的表達來獲取對象ID'GET COREDATA對象

良好的漁獲! (看到它,我爲此提供的表達看起來顯然是錯誤的。)

至於你遇到的異常,這是有道理的。在提取結果中返回的值不是託管對象本身,它只是託管對象的ID。要訪問管理對象,我覺得有以下應該工作:以上

NSManagedObjectID *myObjectID = [dict objectForKey:@"TableNameEntity"]; 
TableNameEntity *tableEntity = (TableNameEntity *)[context objectWithID:myObjectID]; 
tableEntity.column1 

context是的NSManagedObjectContext。

但是,我認爲我更喜歡你的最終解決方案。我不知道你可以將NSExpressionDescriptions與propertiesToFetch數組中的屬性結合起來。很高興知道!

更重要的是,在獲取所需的所有屬性的過程中,獲取所需屬性的速度可能比僅從獲取中獲取對象ID並稍後獲取屬性的速度要快。獲取objectID通常不會觸發實體的錯誤。我相信當你訪問這些屬性時,錯誤將在稍後被解僱。當訪問第一個屬性時,它會觸發一次,或者多次,每個屬性觸發一次。 (我不確定是哪一個。)[有關錯誤的解釋,請參見Firing Faults。]

我的建議是,在propertiesToFetch中包含所有屬性是最好的方法。 (如果您願意,您可以嘗試獲取objectID,但是如果發現速度很慢,則可以返回獲取所有屬性)。

提取請求和表達式記錄不完整。你必須和他們一起玩,以獲得正確的語法。你似乎做得很好。

+0

感謝您的回答。我有一些疑問。 ---在結果中,我得到一個字典,其中有'列值'和'someNumber'的區別。有沒有辦法讓我得到包含差異和DB對象(行)的結果?截至目前我已編碼獲得兩個結果集(數組)。一個包含數據庫對象,另一個包含差異。我將發佈代碼作爲對問題的修改。 – Sahil

+0

salo.dm:請在問題中選中「編輯:獲取coredata對象」。謝謝! – Sahil

+0

請檢查編輯的回覆。 –