2010-10-15 45 views
2

您好我需要在我指定的特定位置(例如通過void *指針)初始化NSObject。對於一些上下文,我寫了一個sqlite3聚合函數。爲了保持這個函數的臨時結果,我必須調用一個sqlite3_aggregate_context函數,它爲我分配一塊內存。我想在這個位置存儲一個NSDecimalNumber。如何在特定地址初始化一個對象(NSObject子類)

到目前爲止,我已經嘗試了兩種方法:通過做

1)allocWithZone,:

void *location = sqlite3_aggregate_context(...); //returns a block of allocated memory of a certain size 

NSDecimalNumber *num = [[NSDecimalNumber allocWithZone:NSZoneFromPointer(location)] initWithInt:0]; 

這不起作用,因爲NSZoneFromPointer返回零。 Docs說這個函數的參數必須是一個先前分配的指針,它是。我不知道這是否意味着使用NSZoneMalloc/Calloc進行分配。

2)

id location = sqlite3_aggregate_function(...); 

location = [[NSDecimalNumber alloc] init]; 

但這種釋放的內存時會導致某種無限遞歸的...不知道這筆交易是什麼。這裏的截圖: http://dl.dropbox.com/u/3002073/Public%20Sync/sqlitefunctionissue.png

任何建議將不勝感激!

回答

4

您無法可靠地確定將在內存中創建對象的位置。 NSZoneFromPointer會失敗,因爲sqlite3 API不使用區域來分配其資源。

如果你想能夠傳遞一個特定的位置,你應該使用指向該對象的指針(因此你基本上存儲了一個指向指針的指針)。然後,您可以從您的聚合函數中讀取這些信息並相應地進行更新。只要確保你不會簡單地讓對象在調用結束時被釋放,而不必注意釋放它(否則你會泄漏)。

因此,舉例來說,你可以這樣做:

NSDecimalNumber** numberLocation = sqlite3_aggregate_context(...); 
*numberLocation = [[NSDecimalNumber alloc] initWithDouble:25.0]; 

您現在可以將儲存在特殊內存區域的對象的引用,並可以訪問它的任何時間:

NSDecimalNumber* storedNumber = *numberLocation; 
NSDecimalNumber* computedNumber = [[NSDecimalNumber alloc] initWithDouble:[storedNumber doubleValue] * someComputation]; 
[storedNumber autorelease]; 
*numberLocation = computedNumber; 

另一方面,我同意馬克的觀點。也許這個不可變的類不是解決你的問題的最佳方案?

+0

我實際上發佈了這個問題,並沒有收回很多信息:http://stackoverflow.com/questions/3919127/how-should-nsdecimalnumbers-be-stored-in-the-database。我需要存儲nsdecimalnumber,因爲我正在使用貨幣,並且在寫入數據庫時​​不能因雙重類型而失去精度。我將它們存儲爲字符串,然後將它們作爲nsdecimal數字讀出來在一個聚合函數中進行求和。因此需要存儲一個暫時的變量總和。我想用這種方法,我將不得不釋放併爲每一行創建一個新的變量... – Ying 2010-10-17 16:57:58

+0

...但我不知道如何做到這一點,否則。我會嘗試這種方法,看看它是否有效。 – Ying 2010-10-17 17:01:44

1

你的第一個版本根本不起作用。 NSZoneFromPointer僅在傳遞從區域分配的指針時才起作用。它被用來讓你可以從同一個區域分配一個對象作爲其他對象。

第二個版本應該可以工作,雖然很難說沒有更多的上下文。你傳遞給sqlite3_aggregate_context作爲要分配的內存的大小是什麼?你完成後如何釋放這些記憶?

第二個版本不起作用,因爲「id」類型實際上是一個指針,因此您將它指向sqlite3_aggregate_context()返回的內存,然後將它指向alloc/init返回的內存。你真的需要存儲一個指針指針來讓它按你想要的方式工作。

NSDecimalNumber是一個不可變的類,因此調用-init(而不是-initWithDecimal :)只是爲了得到一些默認值。隨着函數的進展,用什麼樣的代碼來用新值替換NSNumber?

更重要的是,爲什麼要使用NSDecimalNumber,而不是C整數,或者double,或者其他什麼?

+0

mark,sqlite3_aggregate_context的參數基本上是你想要分配的內存大小。有一個清理回調,所以我可以可靠地清理nsdecimalnumber。我使用NSDecimalNumber,因爲我正在計算幾分之一便士,並需要保持精確度。 – Ying 2010-10-17 17:04:07