你可以这样设置模型:
User <---->> Preference <<-----> PreferenceType
User.name // name string
User.preferences // to-many to Preference
Preference.value // the value, or "selection"
Preference.user // to-one to User
Preference.type // to-one to PreferenceType
Preference.name // name of preference, such as "language"
PreferenceType.preferences // to-many relationship to Preference
您的谓词将需要一个子查询,并且在资源使用方面将非常“昂贵”。我假设允许某些用户具有其他用户没有的偏好,即,虽然我们确实知道可能偏好的总数,但我们不知道某个特定用户的偏好数量。我不能从头顶写下那个查询,我必须考虑一下。 --- 有人吗?
一种实用的方法是首先获取用户子集,例如,具有完全相同昵称的用户。使用这样的谓词获取首选项对象会更简单:
[NSPredicate predicateWithFormat:
@"type.name = 'nickname' && value = %@ && not (user = %@)", userNickname, user];
在一小部分用户(foundPreference.user 引用)上,您可以运行您编写的自定义方法 (hasSamePreferences),您可以在其中迭代首选项并检查是否存在和相等。
-(BOOL)hasSamePreferencesAsUser:(User*)otherUser {
NSSet *myPreferenceKeys = [self.preferences valueForKeyPath:@"type.name"];
NSSet *otherPreferenceKeys = [otherUser.preferences valueForKeyPath:@"type.name"];
if (myPreferenceKeys.count != otherPreferenceKeys.count) {
return NO;
}
for (NSString *key in myPreferenceKeys) {
if (![otherPreferenceKeys containsObject:key]) {
return NO;
}
NSPredicate *keyFilter = [NSPredicate predicateWithFormat:@"type.name = %@", key];
// String only for demonstration
NSString *myValue = [self.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
NSString *otherValue = [otherUser.preferences
filteredArrayUsingPredicate:keyFilter].firstObject;
if (![myValue isEqualToString:otherValue]) {
return NO;
}
}
return YES;
}
顺便说一句,如果您不期望超过 20 个首选项,那么将这些首选项硬编码为 User(或具有一对一的 Settings 实体)的正确命名属性会更加实用关系,如果你愿意)。您的代码将非常易读,并且您的谓词相当简单。