Skip to content

Commit

Permalink
Merge pull request #6570 from realm/tg/freeze-bugs
Browse files Browse the repository at this point in the history
Fix a few bugs with frozen objects in obj-c
  • Loading branch information
tgoyne authored Jun 10, 2020
2 parents 9ff304e + 94e356e commit 6011b7f
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 3 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ x.y.z Release notes (yyyy-MM-dd)
* None.

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-cocoa/issues/????), since v?.?.?)
* None.
* `-[RLMObject isFrozen]` always returned false. ([#6568](https://github.com/realm/realm-cocoa/issues/6568), since 5.0.0).
* Freezing an object within the write transaction that the object was created
in now throws an exception rather than crashing when the object is first
used.
* The schema for frozen Realms was not properly initialized, leading to crashes
when accessing a RLMLinkingObjects property.
([#6568](https://github.com/realm/realm-cocoa/issues/6568), since 5.0.0).

<!-- ### Breaking Changes - ONLY INCLUDE FOR NEW MAJOR version -->

Expand Down
4 changes: 4 additions & 0 deletions Realm/RLMObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ - (instancetype)freeze {
return RLMObjectFreeze(self);
}

- (BOOL)isFrozen {
return _realm.isFrozen;
}

- (RLMNotificationToken *)addNotificationBlock:(RLMObjectChangeBlock)block {
return RLMObjectAddNotificationBlock(self, block, nil);
}
Expand Down
3 changes: 3 additions & 0 deletions Realm/RLMObjectBase.mm
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,9 @@ id RLMObjectFreeze(RLMObjectBase *obj) {
RLMRealm *frozenRealm = [obj->_realm freeze];
RLMObjectBase *frozen = RLMCreateManagedAccessor(obj.class, &frozenRealm->_info[obj->_info->rlmObjectSchema.className]);
frozen->_row = frozenRealm->_realm->import_copy_of(obj->_row);
if (!frozen->_row.is_valid()) {
@throw RLMException(@"Cannot freeze an object in the same write transaction as it was created in.");
}
RLMInitializeSwiftAccessorGenerics(frozen);
return frozen;
}
Expand Down
1 change: 1 addition & 0 deletions Realm/RLMRealm.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,7 @@ - (RLMRealm *)frozenCopy {
try {
RLMRealm *realm = [[RLMRealm alloc] initPrivate];
realm->_realm = _realm->freeze();
realm->_realm->set_schema_subset(_realm->schema());
realm->_realm->read_group();
realm->_dynamic = _dynamic;
realm->_schema = _schema;
Expand Down
33 changes: 33 additions & 0 deletions Realm/Tests/LinkingObjectsTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,39 @@ - (void)testLinkingObjectsOnUnmanagedObject {
@"Linking objects notifications are only supported on managed objects.");
}

- (void)testLinkingObjectsOnFrozenObject {
NSArray *(^asArray)(id) = ^(id arrayLike) {
return [arrayLike valueForKeyPath:@"self"];
};

RLMRealm *realm = [self realmWithTestPath];
[realm beginWriteTransaction];
PersonObject *hannah = [PersonObject createInRealm:realm withValue:@[@"Hannah", @0]];
PersonObject *mark = [PersonObject createInRealm:realm withValue:@[@"Mark", @30, @[hannah]]];
[realm commitWriteTransaction];

PersonObject *frozenHannah = hannah.freeze;
PersonObject *frozenMark = mark.freeze;
XCTAssertEqualObjects(asArray(frozenHannah.parents), (@[frozenMark]));

[realm beginWriteTransaction];
PersonObject *diane = [PersonObject createInRealm:realm withValue:@[@"Diane", @29, @[hannah]]];
[realm commitWriteTransaction];

PersonObject *frozenHannah2 = hannah.freeze;
PersonObject *frozenMark2 = mark.freeze;
PersonObject *frozenDiane = diane.freeze;
XCTAssertEqualObjects(asArray(frozenHannah.parents), (@[frozenMark]));
XCTAssertEqualObjects(asArray(frozenHannah2.parents), (@[frozenMark2, frozenDiane]));

[realm beginWriteTransaction];
[realm deleteObject:hannah];
[realm commitWriteTransaction];

XCTAssertEqualObjects(asArray(frozenHannah.parents), (@[frozenMark]));
XCTAssertEqualObjects(asArray(frozenHannah2.parents), (@[frozenMark2, frozenDiane]));
}

- (void)testFilteredLinkingObjects {
NSArray *(^asArray)(id) = ^(id arrayLike) {
return [arrayLike valueForKeyPath:@"self"];
Expand Down
16 changes: 15 additions & 1 deletion Realm/Tests/ObjectTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ - (void)testIsFrozen {
IntObject *frozen = [managed freeze];
XCTAssertFalse(standalone.isFrozen);
XCTAssertFalse(managed.isFrozen);
XCTAssertFalse(frozen.isFrozen);
XCTAssertTrue(frozen.isFrozen);
}

- (void)testFreezeUnmanagedObject {
Expand Down Expand Up @@ -1455,4 +1455,18 @@ - (void)testFrozenObjectHashing {
}
}

- (void)testFreezeInsideWriteTransaction {
RLMRealm *realm = RLMRealm.defaultRealm;
[realm beginWriteTransaction];
IntObject *obj = [IntObject createInRealm:realm withValue:@[@1]];
RLMAssertThrowsWithReason([obj freeze], @"Cannot freeze an object in the same write transaction as it was created in.");
[realm commitWriteTransaction];

[realm beginWriteTransaction];
obj.intCol = 2;
// Frozen objects have the value of the object at the start of the transaction
XCTAssertEqual(obj.freeze.intCol, 1);
[realm cancelWriteTransaction];
}

@end

0 comments on commit 6011b7f

Please sign in to comment.