0

もともと sqlite に保存されていたデータがあり、最初に使用するときに NSCache にロードされます。NSCache から pickerview オブジェクトにデータをコピーし、そのデータを使用して pickerview (オブジェクト内の "retain") を生成します。

ただし、pickerview オブジェクトのデータが期待どおりではないため、少数のユーザーでクラッシュが発生します。

データソース.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
}
4

2 に答える 2

1

のデータはNSCache安定しておらず、非常に一貫性がありません。アプリケーションをバックグラウンドにしてから再度開くと、クラッシュする可能性があると思います。これにより、NSCache.

NSArrayこの場合は使用しないでください。データがそれほど大きくない場合は を使用するか、そうである場合は を使用することをお勧めしますCoreData

それが役に立ったことを願っています。

于 2013-12-15T08:53:39.530 に答える
1

NSCacheこの目的には使用しません。NSCacheメモリが少ないときに破棄できる時間を格納するために使用するように設計されています。

NSCache は、ピッカー ビューやテーブル ビューの信頼できる情報源としてではなく、アプリがネットワークやディスクにヒットするのを防ぐために使用します。

ドキュメントから

NSCache オブジェクトは、いくつかの点で他の可変コレクションとは異なります。

NSCache クラスにはさまざまな自動削除ポリシーが組み込まれており、システムのメモリを過度に使用しないようになっています。他のアプリケーションがメモリを必要とする場合、システムはこれらのポリシーを自動的に実行します。これらのポリシーが呼び出されると、キャッシュからいくつかのアイテムが削除され、メモリ フットプリントが最小限に抑えられます。

のインスタンスを使用しNSArrayてピッカーをバックアップするだけです。

于 2013-12-15T08:56:36.783 に答える