2012-03-12 10 views
0

plistファイルからデータをロードしようとしています。 NSArrayのNSArrayが含まれており、それぞれ非常に少ないデータ(非常に短い文字列と数値)を含みます。問題は約8000のエントリがあることです。 plistファイル自体は、XMLとして保存された場合は約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メガバイトを取得する理由について任意の手掛かりそのplistをロードしますか?そして、明らかに、検索をキャンセルして元のデータを復元すると、割り当て解除されません。searchBarCancelButtonClicked ...

答えて

0

問題は、セクションごとにNセクションとN行を返すことでした。明らかにベストアイデアではありません。データセットは約8000エントリしかありません。すぐに変更されることはありませんので、そのままコードをそのまま残しておきます(明らかな修正を加えて)。別のブランチで私はCore Dataを試しています。

関連する問題