如何检查NSSet是否包含某种类的对象?

时间:2011-04-29 21:36:13

标签: core-data nsmanagedobject nsset

如何为NSSet实现以下实例方法:

- (BOOL)containsMemberOfClass:(Class)aClass

这就是我想知道的原因:

核心数据模型:enter image description here

如何向用户的授权NSSet添加Facebook授权,但仅限于尚未存在的授权。换句话说,用户可以具有许多授权(如果我将来选择添加Twitter(例如)授权),但是应该只具有每种授权中的一种。所以,if (![myUser.authorizations containsMemberOfClass:[Facebook class]]),然后将Facebook授权实例添加到myUser

5 个答案:

答案 0 :(得分:3)

不幸的是,您必须遍历所有授权并检查:

@interface NSSet (ContainsAdditions)

- (BOOL)containsKindOfClass:(Class)class;
- (BOOL)containsMemberOfClass:(Class)class;

@end

@implementation NSSet (ContainsAdditions)

- (BOOL)containsKindOfClass:(Class)class {
    for (id element in self) {
        if ([element isKindOfClass:class])
            return YES;
    }
    return NO;
}

- (BOOL)containsMemberOfClass:(Class)class {
    for (id element in self) {
        if ([element isMemberOfClass:class])
            return YES;
    }
    return NO;
}

@end

答案 1 :(得分:1)

使用Core Data,最好将NSFetchRequest与NSPredicate一起使用。为此,您必须向Authorization对象添加属性,例如authorizationType。然后,您可以执行以下操作:

NSManagedObjectContext *moc = [self managedObjectContext];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY user.authorizations.authorizationType == %@", @"facebook"];
[request setEntity:[NSEntityDescription entityForName:@"Authorization" inManagedObjectContext:moc]];
[request setPredicate:predicate];

NSError *error = nil;
NSArray *result = [moc executeFetchRequest:request error:&error];

然后,您可以检查result的计数,看它是否存在。使用NSPredicate可以使用Apple围绕CoreData添加的任何优化。以下是Apple Docs

答案 2 :(得分:0)

如果将此实例方法添加到User类?

,该怎么办?
- (BOOL)hasFacebookAuthorization {
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user.id == %@", [self id]];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Facebook"
                                   inManagedObjectContext:managedObjectContext]];
    [fetchRequest setPredicate:predicate];

    NSError *error;
    NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if (!result) {
        // TODO: Handle the error appropriately.
        NSLog(@"hasFacebookAuthorization error %@, %@", error, [error userInfo]);
    }

    return [result count] > 0;
}

答案 3 :(得分:0)

你以错误的方式解决这个问题。如果授权类型是常见且重要的,那么您应该直接在数据模型中对其进行建模,而不是尝试将该结构强加于外部控制器代码中。

如果您有一组固定的授权,那么您应该创建一个实体来为这些授权建模。

Facebook{
    accessToken:string
    experationDate:date
    authorization<-->Authorizations.facebook
}

Google{
    username:string
    password:string
    authorization<-->Authorizations.google
}

Authorizations{
    user<-->User.authorizations
    facebook<-->Facebook.authorization
    google<-->Google.authorization
}

现在,您已在数据模型中捕获了所有授权。要收紧更多东西。您可以向User类添加自定义方法,以控制添加和删除授权。

这里的关键思想是管理数据的所有逻辑应尽可能地封装在数据模型中。这使您可以(1)独立于界面测试所有数据操作,(2)轻松添加和删除界面元素,而不会破坏数据模型。

答案 4 :(得分:0)

老问题,但回答略有不同:

NSPredicate *objectTypeFilter = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:NSClassFromString(@"MyObject")];
}];
NSSet *myObjects =[allObjects filteredSetUsingPredicate:objectTypeFilter];
if (myObjects.count>0) {
    // There was at least one object of class MyObject in the allObjects set
}