あなたが書いた
NSArray *arr = [arrayPDContent filteredArrayUsingArrayPredicate:predicate];
-filteredArrayUsingArrayPredicate:はメソッドではなく、 「filteredArrayUsingArrayPredicate」という用語の検索結果は、同じコンテンツで開いた2つの質問だけなのでNSMutableArray、これはのタイプミスであると想定し-filteredArrayUsingPredicate:ます。
あなたはあなたに使用-[NSArray filteredArrayUsingPredicate:]してNSMutableArray arrayPDContentいて、これが変化することを期待していますarrayPDContent。これは何をするかで-filteredArrayUsingPredicate:はありません。これはのメソッドであり、を含むNSArrayすべてのsで同じ動作をします。その実装は次のようなものであると想像できます。NSArrayNSMutableArray
- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate
{
NSMutableArray *mutableRes = [NSMutableArray array];
for (id obj in self) {
if ([predicate evalutateWithObject:obj]) {
[mutableRes addObject:obj];
}
}
return [mutableRes copy];
}
特に、-filteredArrayUsingPredicate:ターゲットがのインスタンスであっても、これによってターゲットが変更されることはありませんNSMutableArray。
あなたの問題の即時の解決策は書くことです
arrayPDContent = [[arrayPDContent filteredArrayUsingPredicate:predicate] mutableCopy];
代わりに
NSArray *arr = [arrayPDContent filteredArrayUsingPredicate:predicate];
ただし、これを行うことでデータを破棄しているため、これは適切な解決策ではありません。arrayPDContentここで除外された オブジェクトはすべて失われます。
より良い解決策は、述語をプロパティとして保存することです。
@property (nonatomic) NSPredicate *filter;
の実装を変更-numberOfRowsInTableView:し-tableView:objectValueForTableColumn:row:、新しいプロパティを利用します。
- (NSUInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [[arrayPDContent filteredArrayUsingPredicate:[self filter]] count];
}
と
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSUInteger)row
{
return [[[arrayPDContent filteredArrayUsingPredicate:[self filter]] objectAtIndex:row] objectForKey:COLUMN_ID];
}
それよりも
- (NSUInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [arrayPDContent count];
}
と
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSUInteger)row
{
return [[arrayPDContent objectAtIndex:row] objectForKey:COLUMN_ID];
}
フィルター処理された配列が繰り返し計算されているため、これもあまり良い解決策ではありません。さらに良い解決策は、配列をキャッシュしてプロパティを追加することです
@property (nonatomic) NSArray *filteredArrayPDContent;
getter実装を使用してテーブルビューのデリゲートに
- (NSArray *)filteredArrayPDContent
{
if (!_filteredArrayPDContent) {
_filteredArrayPDContent = [arrayPDContent filteredArrayUsingPredicate:[self filter]];
}
return _filteredArrayPDContent;
}
またはが変更されるたびにに設定_filteredArrayPDContentします。nilarrayPDContent[self filter]
編集、追加:
またはが変更されるたびに設定_filteredArrayPDContentする方法の一部を取得するために、メソッドを追加できますnilarrayPDContent[self filter]
- (void)resetFilteredArrayPDContent
{
_filteredArrayPDContent = nil;
}
このメソッドはarrayPDContent、変更または変更する場所から[self filter]呼び出す必要があるため、次の場所でこのメソッドを呼び出す必要があります。
1. 内-filterOnClick::
- (IBAction)filterOnClick(id)sender
{
NSString *age = @"62";
[self setFilter:[NSPredicate predicateWithFormat:@"Age >= ", age]];
[self resetFilteredArrayPDContent];
[gridView reloadData];
}
そして、入力2. した後arrayPDContent:
for (/*...*/) {
//...
NSString *sAge = [NSString stringWithUTFString:sqlite3_column ....];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectAndKeys:sAge, COLUMN_ID, nil];
[arrayPDContent addObject:dictionary];
//...
}
[self resetFilteredArrayPDContent];
インスタンス変数を直接設定するか、メソッド[self setArrayPDContent:]を呼び出すか(標準の角かっこ表記または新しいドット表記を使用するかどうかに関係なく)、の値を設定するたびに-resetFilteredArrayPDContent (A)を呼び出す必要があります。また、( B )を呼び出す必要があります。変更します(、、、、または配列を変更するその他の方法を使用して)。[self arrayPDContent]self.arrayPDContent = //...arrayPDContent-addObject:-removeObject:-filterUsingPredicate:NSMutableArray
編集続き、代替:
上記の代わりに、代わりに:1.の実装を変更することができます。-setFilter:
- (void)setFilter:(NSPredicate *)filter
{
_filter = filter;
[self resetFilteredArrayPDContent];
}
また、インスタンス変数を直接設定したり、他の場所で変更したりするのではなく、呼び出していることを確認してください-setFilter:(角[self setFilter:filter]かっこ---またはドット----表記法を使用してください) 。self.filter = filter_filter-filterOnClick:[self filter]
上記の代わり2.に、メソッドを追加することができます
- (void)addArrayPDContentObject:(id)obj
{
[arrayPDContent addObject:obj];
[self resetFilteredArrayPDContent];
}
ポピュレートするときにそれを呼び出しますarrayPDContent:
for (/*...*/) {
//...
NSString *sAge = [NSString stringWithUTFString:sqlite3_column ....];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectAndKeys:sAge, COLUMN_ID, nil];
[self addArrayPDContentObject:dictionary];
//...
}
他の種類のミューテーションについても同様のメソッドを次のように追加する必要がありますarrayPDContent。
arrayPDContent特定のインデックスにオブジェクトを挿入する場合は、
- (void)insertObject:(id)obj inArrayPDContentAtIndex:(NSUInteger)index
{
[arrayPDContent insertObject:obj atIndex:index];
[self resetFilteredArrayPDContent];
}
と電話
[self insertObject:obj inArrayPDContentAtIndex:index];
それよりも
[arrayPDContent insertObject:obj atIndex:index];
arrayPDContent特定のインデックスからオブジェクトを削除する場合
- (void)removeObjectFromArrayPDContentAtIndex:(NSUInteger)index
{
[arrayPDContent removeObjectAtIndex:index];
[self resetFilteredArrayPDContent];
}
と電話
[self removeObjectFromArrayPDContentAtIndex:index];
それよりも
[arrayPDContent removeObjectAtIndex:index];
など。これらのメソッドの命名規則は、Appleのドキュメントに記載されています。
編集、追加の代替:
この問題に対する最も簡単ですが最悪の解決策は、以前のバージョンをキャッシュし、現在のバージョンを以前のバージョンarrayPDContentとfilter比較して計算_filteredArrayPDContentおよびチェックすることです。プロパティを追加した後
@property (nonatomic) NSArray *oldArrayPDContent;
@property (nonatomic) NSPredicate *oldFilter;
の実装を変更します-filteredArrayPDContent:
- (NSArray *)filteredArrayPDContent
{
if (![[self oldArrayPDContent] isEqualToArray:arrayPDContent]
|| ![[[self oldFilter] predicateFormat] isEqualToString:[[self filter] predicateFormat]]) {
_filteredArrayPDContent = [arrayPDContent filteredArrayUsingPredicate:[self filter]];
[self setOldFilter:[self filter]];
[self setOldArrayPDContent:[arrayPDContent copy]];
}
return _filteredArrayPDContent;
}
のコピーとしてoldArrayPDContent設定されていることに注意してください。 arrayPDContent
繰り返しになりますが、これはパフォーマンスを向上させるための最も迅速なドロップインの代替品かもしれませんが、想像力の範囲で最もスタイリッシュなものではありません。
より良い解決策は、コンテンツ配列に適切に境界を追加することです(これが機能するには、コンテンツ配列が不変である必要があることに注意してください。より正確には、注意せずに他のメソッドNSArrayControllerを使用することはできません)。あなたの行を適切に。-addObject:NSMutableArrayNSTableViewNSArrayController
-setFilterPredicate:このスタイルを使用すると、NSArrayControllerfromを呼び出すだけです-filterOnClick:。