2010-09-10 45 views
0

我已經搜索高低,試圖解決這個內存泄漏,但我無法弄清楚如何讓它消失。我有幾個類用於連接到我的sqlite數據庫並提取信息。目標C類中的內存泄漏iOS

當我使用性能工具運行應用程序時,泄漏,我一直髮現我的所有類都泄漏了內存。

下面是我的代碼。任何幫助解決此泄漏將不勝感激。

tbl_materialsList.h

@interface tbl_materialsList : NSObject { 

NSInteger materialListID; 
NSString *shoppingListID; 
NSString *projectID; 
NSString *materialName; 
NSString *numberOfUnits; 
NSString *purchased; 
NSString *totalPrice; 
NSString *unitPrice; 

} 

@property (nonatomic, readonly) NSInteger materialListID; 
@property (nonatomic, retain) NSString *shoppingListID; 
@property (nonatomic, retain) NSString *projectID; 
@property (nonatomic, retain) NSString *materialName; 
@property (nonatomic, retain) NSString *numberOfUnits; 
@property (nonatomic, retain) NSString *purchased; 
@property (nonatomic, retain) NSString *totalPrice; 
@property (nonatomic, retain) NSString *unitPrice; 

- (id)getDataToDisplay:(NSString *)dbPath :(NSString *)selectStatement; 
- (void)saveData:(NSString *)dbPath :(NSString *)selectStatement; 
- (id)initWithPrimaryKey:(NSInteger)pk; 

tbl_materialsList.m

- (id)getDataToDisplay:(NSString *)dbPath :(NSString *)selectStatement { 


// Init the data Array 
NSMutableArray *data = [[NSMutableArray alloc] init]; 

if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) { 

    NSString *sql = selectStatement; //"select * from tbl_projects"; 
    sqlite3_stmt *selectstmt; 
    if(sqlite3_prepare_v2(database, [sql UTF8String], -1, &selectstmt, NULL) == SQLITE_OK) { 
    //loop thru and fill the array 
    while(sqlite3_step(selectstmt) == SQLITE_ROW) { 
    //reading the results 
    NSInteger primaryKey = sqlite3_column_int(selectstmt, 0); 
    tbl_materialsList *listObj = [[tbl_materialsList alloc] initWithPrimaryKey:primaryKey]; 
    listObj.shoppingListID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)]; 
    listObj.projectID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)]; 
    listObj.materialName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)]; 
    listObj.numberOfUnits = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)]; 
    listObj.purchased = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 5)]; 
    listObj.totalPrice = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 6)]; 
    listObj.unitPrice = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 7)]; 

    [data addObject:listObj]; 
    [listObj release]; 
    } 
    } 

    //release the compiled statment from memory 
    sqlite3_finalize(selectstmt); 

} 

sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory. 

return data; 

} 

回答

0

字符串應該是@property(nonatomic,copy)首先,你需要釋放的數據。 [data release];

+0

爲什麼他們需要'複製'而不是'保留'? – 2010-09-10 15:46:39

+0

@Graham - 我聽說的唯一理由是因爲你可能已經指出你的保留在NSMutableString中,然後可以從你的下面修改。複製阻止了這一點。我不確定爲什麼人們專注於NSString的這個問題(它存在於任何保留的引用中)。 – Peter 2010-09-10 15:50:45

+0

我討厭聽起來很愚蠢,但如果我在返回後發佈數據,看起來沒有任何事情發生。當我遍歷代碼時,它仍然有它的所有對象。如果我之前發佈,它會崩潰,因爲我期望。 – 2010-09-10 15:56:58

1

您的tbl_materialslist是否實現了一個dealloc,將所有保留屬性設置爲nil?如果沒有,即使你的listObj被釋放,它們也會全部泄漏。

+0

嗨,感謝您的快速回復。我做了以下... - (void)dealloc { \t [ shoppingListID釋放]; \t [專案編號釋放]; \t [materialName釋放]; \t [numberOfUnits釋放]; \t [購relea SE]; \t [totalPrice release]; \t [unitPrice release]; \t [super dealloc]; } – 2010-09-10 15:47:46

+0

對我來說這看起來很好。希恩是正確的,你還必須發佈數據。 – Peter 2010-09-10 16:11:43

3

你的最後一行:

return data; 

應該是:

return [data autorelease]; 

除非,當然,你打算返回的數據對象被調用者擁有,那麼你應該做的方法名在該方法中符合Objective-C命名約定,返回保留計數爲+1的對象應包含「複製」,「創建」或「新建」一個單詞;

但我懷疑這不是你想要的。

+0

當我返回[數據autorelease];該應用程序崩潰。我基本上得到這些數據並將其加載到一個NSMutableArray中,並使用它來顯示錶中的材料列表。當我查看泄漏工具時,它顯示100%處於調用狀態,然後當我進入此代碼時,它顯示listObj.materialName,itemCost等各個不同的百分比。 – 2010-09-10 16:24:44

+0

使[數據自動釋放]更改時,還需要在調用getDataToDisplay的方法中保留生成的數據對象:然後確保在完成後可以正確釋放它。 – logancautrell 2010-09-10 16:35:06

+0

我正在做的調用是tbl_materialsList * dbaseTable = [[tbl_materialsList alloc] init]; \t NSString * statement = [NSString stringWithFormat:@「select * from tbl_materialsList where projectID =%d」,projectData.projectID]; \t NSArray * data = [dbaseTable getDataToDisplay:[appDelegate getDBPath]:statement];我一直認爲數據會被自動釋放... – 2010-09-10 16:56:39

0

一個不相關的建議:

永遠不會返回一個對象作爲(id),除非它是絕對必要。例如,您的getDataToDisplay::

-(NSMutableArray*)getDataToDisplay:(NSString *)dbPath :(NSString *)selectStatement; 

這樣,你可以得到更多的編譯器警告,當你犯了一個錯誤。

我想這是一本促進這種不良習慣的iPhone編程書。該書的作者應該被束縛,書應該被燒燬...:p