Skip to content

Commit

Permalink
Fix more cases where assigning an RLMArray property to itself would c…
Browse files Browse the repository at this point in the history
…lear the RLMArray
  • Loading branch information
tgoyne committed Sep 7, 2017
1 parent 3971ecb commit 8767a67
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 17 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
x.x.x Release notes (yyyy-MM-dd)
=============================================================

### API Breaking Changes

* None.

### Enhancements

* None.

### Bugfixes

* Fix more cases where assigning an RLMArray property to itself would clear the
RLMArray.

2.10.0 Release notes (2017-08-21)
=============================================================

Expand Down
2 changes: 1 addition & 1 deletion Realm/ObjectStore
2 changes: 2 additions & 0 deletions Realm/RLMAccessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class RLMAccessorContext {
RLMOptionalId default_value_for_property(realm::ObjectSchema const&,
std::string const& prop);

bool is_same_list(realm::List const& list, id v) const noexcept;

template<typename Func>
void enumerate_list(__unsafe_unretained const id v, Func&& func) {
for (id value in v) {
Expand Down
26 changes: 10 additions & 16 deletions Realm/RLMAccessor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -136,23 +136,13 @@ void setValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained id<NSFastEnumeration> const value) {
RLMVerifyInWriteTransaction(obj);

realm::List list(obj->_realm->_realm, obj->_row.get_linklist(colIndex));
if ([(id)value respondsToSelector:@selector(isBackedByList:)] && [(id)value isBackedByList:list]) {
return; // self-assignment is a no-op
realm::List list(obj->_realm->_realm, *obj->_row.get_table(), colIndex, obj->_row.get_index());
RLMClassInfo *info = obj->_info;
if (list.get_type() == realm::PropertyType::Object) {
info = &obj->_info->linkTargetType(obj->_info->propertyForTableColumn(colIndex).index);
}

list.remove_all();
if (!value || (id)value == NSNull.null) {
return;
}

RLMAccessorContext ctx(obj->_realm,
obj->_info->linkTargetType(obj->_info->propertyForTableColumn(colIndex).index));
translateError([&] {
for (id element in value) {
list.add(ctx, element);
}
});
RLMAccessorContext ctx(obj->_realm, *info);
translateError([&] { list.assign(ctx, value, false); });
}

void setValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
Expand Down Expand Up @@ -863,3 +853,7 @@ static auto to_optional(__unsafe_unretained id const value, Fn&& fn) {
{
return RLMOptionalId{defaultValue(@(prop.c_str()))};
}

bool RLMAccessorContext::is_same_list(realm::List const& list, __unsafe_unretained id const v) const noexcept {
return [v respondsToSelector:@selector(isBackedByList:)] && [v isBackedByList:list];
}
4 changes: 4 additions & 0 deletions Realm/Tests/ArrayPropertyTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,8 @@ - (void)testUnmanagedAssignment {
// Self-assignment is a no-op
array2.intArray = array2.intArray;
XCTAssertEqualObjects([array2.intArray valueForKey:@"self"], (@[io2, io3]));
array2[@"intArray"] = array2[@"intArray"];
XCTAssertEqualObjects([array2[@"intArray"] valueForKey:@"self"], (@[io2, io3]));
}

- (void)testManagedAssignment {
Expand Down Expand Up @@ -1070,6 +1072,8 @@ - (void)testManagedAssignment {
// Self-assignment is a no-op
array2.intArray = array2.intArray;
XCTAssertEqualObjects([array2.intArray valueForKey:@"intCol"], (@[@2, @3]));
array2[@"intArray"] = array2[@"intArray"];
XCTAssertEqualObjects([array2[@"intArray"] valueForKey:@"intCol"], (@[@2, @3]));

[realm cancelWriteTransaction];
}
Expand Down

0 comments on commit 8767a67

Please sign in to comment.