Realm.io - objective-c中的复合主键

时间:2015-08-28 18:20:20

标签: objective-c primary-key realm

我正在努力寻找一种方法,使用Realm.io和Objective-c将多个属性组合成一个主键。

以此对象为例:

@interface Beacon : RLMObject

@property NSString *uuid;
@property int major;
@property int minor;

@end

RLM_ARRAY_TYPE(Beacon)

我如何组合,例如uuid,major和minor成为一个主键?

2 个答案:

答案 0 :(得分:2)

我在当前项目中如何完成它是为复合键添加新属性,使其成为主键。然后,覆盖复合键的所有部分的setter,并调用更新复合键的函数。

我的ObjC很弱,所以我无法为您提供用该语言编写的可靠示例,但这里有一个可能有帮助的Swift示例。

var func = function(_this) {
    return function() {
        document.write('called!');
    };
};

var onReady = func(this); // In your code, the declation of func and its exection are done together

// At this point onReady is equal to the inner function
// function() {
//    document.write('called!');
// }

$(onReady);

答案 1 :(得分:2)

这是Objective-C解决方案。它利用了只能覆盖ignoredProperties的事实。它比Swift版本更冗长,但它有效,所以如果你需要ObjC中的复合键,这可能是你最好的选择。一个可能的限制是公共属性的KVO不起作用,但是,因为Realm期望在将对象添加到Realm之后主键保持不变,所以这种限制可能很小。如果你确实想要KVO,你可以通过注册in this document from Apple所描述的从属密钥来解决它。

在CompositeKeyObject.h中:

@interface CompositeKeyObject : RLMObject

@property (nonatomic, strong) NSString* partOne;
@property (nonatomic, strong) NSString* partTwo;

@end

在CompositeKeyObject.m中:

@interface CompositeKeyObject ()

@property (nonatomic, strong) NSString* partOneValue;
@property (nonatomic, strong) NSString* partTwoValue;
@property (nonatomic, strong) NSString* compositeKey;

@end

@implementation CompositeKeyObject

- (instancetype)initWithValue:(id)value
{
    // Need to make a copy and set the correct "value" properties.
    // Otherwise, the object won't be created properly. 
    NSMutableDictionary* valueCopy = [value mutableCopy];
    if(valueCopy[@"partOne"] != nil) {
        valueCopy[@"partOneValue"] = valueCopy[@"partOne"];
    }
    if(valueCopy[@"partTwo"] != nil) {
        valueCopy[@"partTwoValue"] = valueCopy[@"partTwo"];
    }

    self = [super initWithValue:[valueCopy copy]];
    if(self != nil) {
        // Make sure primary key is in sync.
        [self updatePrimaryKey];
    }
    return self;
}

- (void)setPartOne:(NSString *)partOne
{
    self.partOneValue = partOne;
    [self updatePrimaryKey];
}

- (void)setPartTwo:(NSString *)partTwo
{
    self.partTwoValue = partTwo;
    [self updatePrimaryKey];
}

- (NSString*)partOne
{
    return self.partOneValue;
}

- (NSString*)partTwo
{
    return self.partTwoValue;
}

- (void)updatePrimaryKey
{
    self.compositeKey = [NSString stringWithFormat:@"%@ <><><> %@", self.partOne, self.partTwo];
}

+ (NSString *)primaryKey
{
    return @"compositeKey";
}

+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args {
    predicateFormat = [predicateFormat stringByReplacingOccurrencesOfString:@"partOne" withString:@"partOneValue"];
    predicateFormat = [predicateFormat stringByReplacingOccurrencesOfString:@"partTwo" withString:@"partTwoValue"];
    return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}

+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args {
    predicateFormat = [predicateFormat stringByReplacingOccurrencesOfString:@"partOne" withString:@"partOneValue"];
    predicateFormat = [predicateFormat stringByReplacingOccurrencesOfString:@"partTwo" withString:@"partTwoValue"];
    return [self objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}

@end

单位测试:

- (void)testCompositeObject
{
    CompositeKeyObject* object = [[CompositeKeyObject alloc] init];
    object.partOne = @"ONE";
    object.partTwo = @"TWO";

    RLMRealm* realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [realm addObject:object];
    }];

    XCTAssertNotNil([CompositeKeyObject objectForPrimaryKey:@"ONE <><><> TWO"]);

    object = [[CompositeKeyObject alloc] init];
    object.partOne = @"ONE";
    object.partTwo = @"TWO";

    [realm transactionWithBlock:^{
        XCTAssertThrows([realm addObject:object]);
    }];
}

- (void)testCompositeObject2
{
    CompositeKeyObject* object = [[CompositeKeyObject alloc] initWithValue:@{@"partOne": @"ONE", @"partTwo": @"TWO"}];

    RLMRealm* realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [realm addObject:object];
    }];

    XCTAssertNotNil([CompositeKeyObject objectForPrimaryKey:@"ONE <><><> TWO"]);
    object = [[CompositeKeyObject alloc] initWithValue:@{@"partOne": @"ONE", @"partTwo": @"TWO"}];

    [realm transactionWithBlock:^{
        XCTAssertThrows([realm addObject:object]);
    }];
}