-2

在我的應用程序中,我有一個到sqlite3數據庫的連接。我做了一個包裝類,在這個包裝類中我有一個NSMutableDictionary和NSMutableArray。自定義SQLite包裝器中的內存泄漏

每次運行查詢時,我都會從dictonary和rapper類中的數組中運行I​​(我不會釋放它)。然後將查詢結果添加到數組和字典中。該字典包含另一個子句。

我有一個tableViewController,在這個類我用我的說唱類從數據庫中獲取數據,並將其複製到我的tableviewcontroller變量:

.H

 @interface BrandViewController : UIViewController 
<UITableViewDataSource , UITableViewDelegate> 
{ 
    FairPriceDatabaseView *FairPriceDB; 
    NSArray *brandsIDs; 
    NSMutableDictionary *brandsRecords; 
    UITableView *tableView; 
} 

.M

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self loadBrandsIDs]; 
    [tableView reloadData]; 
} 
- (void)dealloc {[brandsRecords release]; 
    [brandsIDs release]; 
    [super dealloc]; 
} 
-(NSArray *) loadBrandsIDs 
{ 
    [self loadBrandsDB]; 

    [brandsIDs release]; 
    brandsIDs = [[FairPriceDB getBrandIDs]copy]; 

    [brandsRecords release]; 
    **brandsRecords = [[FairPriceDB getBrandIDs_NSDictionary]copy];** 

    [FairPriceDB release]; 
    FairPriceDB = nil; 
    return brandsIDs; 
} 
- (FairPriceDatabaseView *) loadBrandsDB { 
    if (!FairPriceDB) 
     FairPriceDB = [[FairPriceDatabaseView alloc] initWithFairPriceDatabaseViewFilename:@"b.db"]; 
    return FairPriceDB; 
} 

當測試我得到內存泄漏的星號(brandsRecords = [[FairPriceDB getBrandIDs_NSDictionary]copy];) 內存泄漏時,我改變tableviewcontroller並回到這些tableviewcontrollers發生....

我想知道,我做這個正確的方式?爲什麼會有泄漏?

另外,每當我發佈一個NSMutableDictionary,我是否還需要釋放其中包含或不包含的子字典?

FairPriceDataBaseViewController.h(包裝類)

@interface FairPriceDatabaseView { 
    NSMutableArray * idList; 
    NSMutableDictionary * recordList; 
} 

FairPriceDataBaseViewController.m(包裝類)

  - (NSArray *) getBrandIDs { 
       NSDictionary * row; 
       [idList removeAllObjects]; // reset the array 
       for (row in [self getQuery:@"SELECT productID,brandName FROM product GROUP BY brandName;"]) 
        [idList addObject:[row objectForKey:@"productID"]]; 
       return idList; 
      } 

      -(NSDictionary *) getBrandIDs_NSDictionary{ 
       [recordList removeAllObjects]; 
       [idList removeAllObjects]; 
       [self getBrandIDs]; 

       NSNumber * rowid; 
       for(rowid in [self idList]) 
        [recordList setObject:[self getProductRow:rowid] forKey:rowid]; 

       return recordList; 
      } 
     - (NSDictionary *) getProductRow: (NSNumber *) rowid { 
      self.tableName = @"select * from product where productID = ?"; 
      return [self getRow:rowid]; 
     } 
     -(FairPriceDatabaseView *) initWithFairPriceDatabaseViewFilename: (NSString *) fn 
     { 
      if((self = (FairPriceDatabaseView *) [Super initWithDBFilename:fn])) 
      { 
        idList = [[NSMutableArray alloc] init]; 
        recordList = [[NSMutableDictionary alloc]init]; 
      } 
       [self setDefaults]; 
       return self; 
     } 
+0

您可以發佈getAllrecordByRecords的代碼嗎? – zpasternack

+2

那麼,這甚至是你的真實代碼,或者你記得它是什麼?另外,調用實例變量「NSArray ...」並不是一個好習慣。變量名應該以小寫字母開頭,當然不應該與框架類的名字空間衝突。 – jrturton

+0

所以sry,因爲這是我第一次在窗體上發佈一個問題,現在我添加所有真正的代碼,我也有一個說唱歌手類... – Danial

回答

1

請閱讀objective-C memory management guidelines。總之,您必須將所有保留操作(retain,new,init,copy)與發佈進行平衡。

由於您正在清空並重新填充結果字典和數組,而不是創建一個新的結果,然後複製結果,您將保留此對象而不會釋放它。如果你不止一次地這樣做,那麼你將失去對前一個值的引用,所以你現在有內存泄漏。

您需要在分配新值之前釋放先前的值,或者更好地創建保留屬性並通過合成存取器添加新值。

+0

請您給我更詳細的解釋,代碼或鏈接,謝謝 – Danial

+0

我剛剛完成了Objective-C內存管理指南,但仍然無法解決這個內存泄漏問題......關於您的答案的唯一好處我可以以某種方式想想我的應用程序是,你說:「如果你這樣做不止一次」...你能指導我給我一些例子,因爲當我想我可以說當它比一次更高時,我改變viewcontroller發生泄漏事件.. – Danial

+1

@liligago - 作爲一個不同的問題,在上面的代碼中使用'if(brandsRecords)[brandsRecords release];'是一種不好的做法,並且可能導致崩潰。 'brandsRecords'在釋放時不會自動變爲零,所以這個條件是無用的,並且如果'brandsRecords'已經被釋放,會導致崩潰。 –

0

[super dealloc];應該是-dealloc方法的最後一行。在你的代碼中,你首先放置它。

這可能會導致意外的行爲,如未正確釋放該點之後執行的對象,包括brandsRecords。當BrandViewController被釋放時,這可能會導致泄漏,因爲它的實例變量可能永遠不會被釋放。

而且,我對jrturton的答案評論說,不這樣做:

if(brandsIDs) 
     [brandsIDs release]; 

這是一個無用的條件,因爲如果brandsIDs已釋放,也不會是零默認情況下(除非你使用弱指針,你不在這裏),你的應用程序會在這個時候崩潰。如果它是零,發送一個釋放到零將不會做任何事情,那麼爲什麼還要在那裏有if語句?只需使用[brandsIDs release];

+0

謝謝你的幫助... – Danial

+0

我已經應用這兩個問題,但仍然面臨着內存泄漏.... – Danial