2012-03-12 35 views
0

我想從plist文件中加載一些數據。它包含一個非常少數據NSDictionaries的NSArray(一個非常短的字符串和一個數字)。問題是它有大約8000個條目。當存儲爲XML時,plist文件本身約爲900 kB,當以二進制形式存儲時約爲350 kB,但顯然當它被加載到內存時,它會擴展到大約510 MB,這似乎是使用分配分析器發生的情況。這就像磁盤大小的50-60k倍。帶有一系列字典的plist文件的內存開銷是多少?

起初我以爲肯定有某種錯誤,但後來我意識到我對可可的東西的內存開銷知之甚少。無論如何。我加載plist中是這樣的:

NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"localita" ofType:@"plist"]]; 

然後我把它分配給該自定義視圖控制器的屬性(非原子,強)我有

[cbVC setData:data]; 
[cbVC setFilteredData:data]; 

我之前重寫使用setData但我改通過這種方式來看看這是否是一個問題 - 事實並非如此。所以,這就是接口:

@protocol CityBrowserDelegate <NSObject> 

- (void)cityPicked:(NSString *)cityName; 

@end 

@interface CityBrowserViewController : UIViewController <UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate> 

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope; 
- (IBAction)selectionFinished:(id)sender; 

@property (nonatomic, strong) NSMutableArray *data; 
@property (nonatomic, strong) NSMutableArray *filteredData; 

@property (nonatomic, strong) IBOutlet UITableView *tableView; 

@property (nonatomic, strong) IBOutlet id<MyPopoverControllerDelegate, CityBrowserDelegate> delegate; 

@end 

,這是實現(我去掉了不相關的部分)

@implementation CityBrowserViewController 

@synthesize data = _data; 
@synthesize filteredData = _filteredData; 
@synthesize tableView = _tableView; 
@synthesize delegate = _delegate; 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return [self.filteredData count]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return [self.filteredData count] == 0 ? 1 : [self.filteredData count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *cellID = @"BasicCell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 
    if(!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; 
    } 
    if([self.filteredData count] == 0) { 
     [cell.textLabel setText:@"Nessun risultato"]; 
    } else { 
     [cell.textLabel setText:[[self.filteredData objectAtIndex:indexPath.row] valueForKey:@"Name"]]; 
    } 
    return cell; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *name = [[self.filteredData objectAtIndex:indexPath.row] valueForKey:@"Name"]; 
    [self.delegate cityPicked:name]; 
} 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { 
    [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]]; 

    // Return YES to cause the search result table view to be reloaded. 
    return YES; 
} 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { 
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]]; 

    // Return YES to cause the search result table view to be reloaded. 
    return YES; 
} 

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { 
    _filteredData = _data; 
} 

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope { 
    [_filteredData removeAllObjects]; // First clear the filtered array. 

    // YES, I KNOW, but it seems to be quite fast nonetheless... 
    NSDictionary *city; 
    for (city in _data) { 
     NSString *cityName = [city valueForKey:@"Name"]; 
     NSComparisonResult result = [cityName compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])]; 
     if (result == NSOrderedSame) { 
      [_filteredData addObject:city]; 
     } 
    } 
} 

- (void)selectionFinished:(id)sender { 
    [self.delegate dismissPopover]; 
} 

@end 

現在:爲什麼我收到510 MB內存的任何線索分配,當我加載plist?顯然它不會被取消分配,當我取消搜索並恢復原始數據在searchBarCancelButtonClicked ...

回答

0

問題是,我返回N節和每行N行,給定N數據集的大小。顯然不是最好的想法。該數據集只有大約8000個條目,並且不會很快改變,所以現在我將代碼保留原樣(顯而易見的修正)。在一個單獨的分支中,我正在試驗Core Data。