0
NSArray *arrClient = [[NSArray alloc] initWithObjects:@"record 1", @"record 2", nil];
NSArray *arrServer = [[NSArray alloc] initWithObjects:@"record 1", @"record 3", nil];

にまだ存在しないエントリのみをフィルタリングする述語arrServerを適用したいと思いますarrClient。たとえば、この場合record 1、両方の配列に存在し、無視されるため、「レコード 3」文字列を持つ 1 つのエントリを持つ配列のみが返されます。

これは可能ですか?

アップデート

以下の答えは素晴らしいです。結局、私がやっていることは意味があるかどうかを確認するために、実際の例を示す必要があると思います. (私はまだ以下のコンパクトバージョンを提供しています)

clientItems のタイプは FTRecord (Core Data) になります。

@interface FTRecord : NSManagedObject
...
@property (nonatomic) NSTimeInterval recordDate;

@end

@implementation FTRecord
...
@dynamic recordDate;

@end

以下のこのクラスは、REST サービスから json を解析するためのホルダーです。したがって、前述の serverItems はこのタイプになります。

@interface FTjsonRecord : NSObject <JSONSerializable>
{

}

@property (nonatomic) NSDate *recordDate;

@implementation FTjsonRecord

- (NSUInteger)hash
{
    return [[self recordDate] hash];
}

- (BOOL)isEqual:(id)object
{
    if ([object isKindOfClass:[FTjsonRecord self]]) {
        FTjsonRecord *other = object;
        return [[self recordDate] isEqualToDate:[other recordDate]];
    }
    else if ([object isKindOfClass:[FTRecord self]]) {
        FTRecord *other = object;
        return [[self recordDate] isEqualToDate:[NSDate dateWithTimeIntervalSinceReferenceDate:[other recordDate]]];
    }
    else {
        return NO;
    }
}

ウェインの例では、これはうまくいくようです。今、これは実現可能ですか?serverItems は一時的なものであり、サーバーとの同期にのみ使用され、破棄されることに注意してください。clientItems はそのまま残ります。

更新 2:

今回はManuのソリューションを試しています:

クライアント DBStore でこのメソッドを作成しました。このメソッドは、述語によって呼び出されます。使用できない理由containsObjectは、serverItems と clientItems のクラス タイプが同じタイプではないためです。

-(BOOL)recordExistsForDate:(NSDate *)date
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"recordDate == %@", date];
    NSArray *arr = [allRecords filteredArrayUsingPredicate:predicate];
    if (arr && [arr count] > 0) {
        return YES;
    } else {
        return NO;
    }
}

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(FTjsonRecord *evaluatedObject, NSDictionary *bindings) {
                return ![store recordExistsForDate:[evaluatedObject recordDate]];
}];

NSSet *set = [[serverRecords items] filteredSetUsingPredicate:predicate]; 

ただし、このソリューションについて心配しているのは、clientItems (allRecords) からの線形読み取りです。配列で述語を使用することがどれほど効率的かはわかりません。これを達成するためのより良い方法があるかどうか疑問に思います。

4

2 に答える 2

1

NSSet他のセットとの和、積、差(マイナス)を求めるのに使えます。これは、あなたがやろうとしていることにより正確に一致します。

NSMutableSet *serverItems = [[NSMutableSet alloc] init];
[arrServerItems addObjectsFromArray:arrServer];

NSSet *clientItems = [[NSSet alloc] init];
[clientItems addObjectsFromArray:arrClient];

[arrServerItems minus:clientItems];

ただし、これにより注文情報が削除されます。

述語には、次を使用できます。

NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", arrClient];
于 2013-10-28T16:41:24.317 に答える
0

使用する述語に依存します。

これを使用して引数の配列を使用できます

[NSPredicate predicateWithFormat:<#(NSString *)#> argumentArray:<#(NSArray *)#>];

配列内のオブジェクトを使用して述語を作成します

またはブロックで述語を使用する

[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    <#code#>
}]

ブロック内でオブジェクトを評価し、配列内のオブジェクトと比較します

あなたができる可能なチェックは次のとおりです。

return ![arrClient containsObject:evaluatedObject];

arrClient に含まれるオブジェクトを除外します

containsObject: 'isEqual:' を使用してオブジェクトを比較します

于 2013-10-28T15:59:01.423 に答える