我正在尝试从plist文件加载一些数据。它包含一个NSArray的NSDuraries,每个都有很少的数据(一个非常短的字符串和一个数字)。问题是它有大约8000个条目。当作为XML存储时,plist文件本身大约为900 kB,当存储为二进制时,plist文件大约为350 kB,但显然当它被加载到内存中时,它扩展到大约510 MB,这就是使用分配分析器的情况。这就像磁盘大小的50-60k倍。
起初我认为肯定会出现某种错误,但后来我意识到我对Cocoa中的东西的内存开销很少。无论如何。我像这样加载了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
现在:关于为什么在加载该plist时分配510 MB内存的任何线索?显然,当我取消搜索并恢复searchBarCancelButtonClicked
中的原始数据时,它不会被取消分配...
答案 0 :(得分:0)
问题是我给N个部分返回了N个部分,给定N是数据集的大小。显然不是最好的主意。数据集只有大约8000个条目,并且它不会很快改变,所以现在我将保留代码(明显更正)。在一个单独的分支中,我正在尝试核心数据。