I have some data that was originally stored in sqlite and will be loaded to NSCache when first used. I copy the data from NSCache to a pickerview object and use the data to generate pickerview("retain" in the object).
However, a small amount of users encounter crashes because the data in pickerview object is not as expected.
Datasource.m:
- (NSDictionary *)getAllCurrenciesForCache {
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"CurrencyList" ofType:@"json"]];
NSDictionary *dict = [data objectFromJSONData];
return dict;
}
- (NSArray *)getCurrencyList {
NSDictionary *currencies = [cache objectForKey:@"key"];
if(!currencies){
NSDictionary *currencies = [self getAllCurrenciesForCache];
[cache setObject:currencies forKey:@"key"];
}
NSArray *keys = [currencies allKeys];
if(keys){ // do some sorting
return [keys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}
// shouldn't be here
return nil;
}
ViewController.m:
NSArray *data = [datasource getCurrencyList];
NSMutableArray *currencies = [[NSMutableArray alloc] init];
for (NSString *abbr in data) {
[currencies addObject:[[MyClass alloc] initWithAbbr:abbr]];
}
MyPicker *picker = [[MyPicker alloc] initWithData:[NSArray arrayWithArray:currencies]];
MyPicker.h:
@property (nonatomic, retain) NSArray *currencies;
MyPicker.m:
- (id)initWithData:(NSArray *)data {
self = [super init];
if (self) {
self.currencies = data;
self.datasource = self;
self.delegate = self;
}
return self;
}
#pragma mark - UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return self.currencies.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
// sometimes crashes
MyClass *currency = self.currencies[row];
return [currency showString];
}
#pragma mark - UIPickerViewDelegate
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
[self notifySelection];
}
- (void)notifySelection {
NSInteger index = [self selectedRowInComponent:0];
// here may crash because of index out of bound
MyClass *currency = self.currencies[index];
// send the selected currency to view controller
}
The data in the
NSCache
aren't stable, and are super inconsistent. I believe you can get a crash if you put your application in the background then reopened it, this will delete theNSCache
.You shouldn't use it in the case, I believe, I would suggest using either
NSArray
, if data are not that huge, or go withCoreData
if they were.Hope that helped.