Skip to content

Commit c777ff5

Browse files
authored
Fix comparing unmanaged lists (#6845)
1 parent 709425f commit c777ff5

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ x.y.z Release notes (yyyy-MM-dd)
77
* When using `Realm.write(withoutNotifying:)` there was a chance that the
88
supplied observation blocks would not be skipped when in a write transaction.
99
([Object Store #1103](https://github.com/realm/realm-object-store/pull/1103))
10+
* Comparing two identical unmanaged `List<>`/`RLMArray` objects would fail.
11+
([#5665](https://github.com/realm/realm-cocoa/issues/5665)).
1012

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

Realm/RLMArray.mm

+9
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,15 @@ - (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
514514
return [_backingArray objectsAtIndexes:indexes];
515515
}
516516

517+
- (BOOL)isEqual:(id)object {
518+
if (auto array = RLMDynamicCast<RLMArray>(object)) {
519+
return !array.realm
520+
&& ((_backingArray.count == 0 && array->_backingArray.count == 0)
521+
|| [_backingArray isEqual:array->_backingArray]);
522+
}
523+
return NO;
524+
}
525+
517526
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
518527
options:(NSKeyValueObservingOptions)options context:(void *)context {
519528
RLMValidateArrayObservationKey(keyPath, self);

Realm/RLMListBase.mm

+10
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ - (void)addObserver:(id)observer
8282
[super addObserver:observer forKeyPath:keyPath options:options context:context];
8383
}
8484

85+
- (BOOL)isEqual:(id)object {
86+
if (auto array = RLMDynamicCast<RLMListBase>(object)) {
87+
return !array._rlmArray.realm
88+
&& ((self._rlmArray.count == 0 && array._rlmArray.count == 0) ||
89+
[self._rlmArray isEqual:array._rlmArray]);
90+
}
91+
return NO;
92+
}
93+
8594
@end
8695

8796
@implementation RLMLinkingObjectsHandle {
@@ -144,4 +153,5 @@ - (RLMResults *)results {
144153
_realm = nil;
145154
return _results;
146155
}
156+
147157
@end

Realm/Tests/ArrayPropertyTests.m

+43
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,49 @@ - (void)testUnmanaged {
287287
__unused ArrayPropertyObject *obj = [[ArrayPropertyObject alloc] initWithValue:@[@"n", @[], @[[[IntObject alloc] initWithValue:@[@1]]]]];
288288
}
289289

290+
- (void)testUnmanagedComparision {
291+
RLMRealm *realm = [self realmWithTestPath];
292+
293+
ArrayPropertyObject *array = [[ArrayPropertyObject alloc] init];
294+
ArrayPropertyObject *array2 = [[ArrayPropertyObject alloc] init];
295+
296+
array.name = @"name";
297+
array2.name = @"name2";
298+
XCTAssertNotNil(array.array, @"RLMArray property should get created on access");
299+
XCTAssertNotNil(array2.array, @"RLMArray property should get created on access");
300+
XCTAssertTrue([array.array isEqual:array2.array], @"Empty arrays should be equal");
301+
302+
XCTAssertNil(array.array.firstObject, @"No objects added yet");
303+
XCTAssertNil(array2.array.lastObject, @"No objects added yet");
304+
305+
StringObject *obj1 = [[StringObject alloc] init];
306+
obj1.stringCol = @"a";
307+
StringObject *obj2 = [[StringObject alloc] init];
308+
obj2.stringCol = @"b";
309+
StringObject *obj3 = [[StringObject alloc] init];
310+
obj3.stringCol = @"c";
311+
[array.array addObject:obj1];
312+
[array.array addObject:obj2];
313+
[array.array addObject:obj3];
314+
315+
[array2.array addObject:obj1];
316+
[array2.array addObject:obj2];
317+
[array2.array addObject:obj3];
318+
319+
XCTAssertTrue([array.array isEqual:array2.array], @"Arrays should be equal");
320+
[array2.array removeLastObject];
321+
XCTAssertFalse([array.array isEqual:array2.array], @"Arrays should not be equal");
322+
[array2.array addObject:obj3];
323+
XCTAssertTrue([array.array isEqual:array2.array], @"Arrays should be equal");
324+
325+
[realm beginWriteTransaction];
326+
[realm addObject:array];
327+
[realm commitWriteTransaction];
328+
329+
XCTAssertFalse([array.array isEqual:array2.array], @"Comparing a managed array to an unmanaged one should fail");
330+
XCTAssertFalse([array2.array isEqual:array.array], @"Comparing a managed array to an unmanaged one should fail");
331+
}
332+
290333
- (void)testUnmanagedPrimitive {
291334
AllPrimitiveArrays *obj = [[AllPrimitiveArrays alloc] init];
292335
XCTAssertTrue([obj.intObj isKindOfClass:[RLMArray class]]);

RealmSwift/Tests/ListTests.swift

+35
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,41 @@ class ListTests: TestCase {
585585
}
586586
}
587587
}
588+
589+
func testUnmanagedListComparison() {
590+
let obj = SwiftIntObject()
591+
obj.intCol = 5
592+
let obj2 = SwiftIntObject()
593+
obj2.intCol = 6
594+
let obj3 = SwiftIntObject()
595+
obj3.intCol = 8
596+
597+
let objects = [obj, obj2, obj3]
598+
let objects2 = [obj, obj2]
599+
600+
let list1 = List<SwiftIntObject>()
601+
let list2 = List<SwiftIntObject>()
602+
XCTAssertEqual(list1, list2, "Empty instances should be equal by `==` operator")
603+
604+
list1.append(objectsIn: objects)
605+
list2.append(objectsIn: objects)
606+
607+
let list3 = List<SwiftIntObject>()
608+
list3.append(objectsIn: objects2)
609+
610+
XCTAssertTrue(list1 !== list2, "instances should not be identical")
611+
612+
XCTAssertEqual(list1, list2, "instances should be equal by `==` operator")
613+
XCTAssertNotEqual(list1, list3, "instances should be equal by `==` operator")
614+
615+
XCTAssertTrue(list1.isEqual(list2), "instances should be equal by `isEqual` method")
616+
XCTAssertTrue(!list1.isEqual(list3), "instances should be equal by `isEqual` method")
617+
618+
XCTAssertEqual(Array(list1), Array(list2), "instances converted to Swift.Array should be equal")
619+
XCTAssertNotEqual(Array(list1), Array(list3), "instances converted to Swift.Array should be equal")
620+
list3.append(obj3)
621+
XCTAssertEqual(list1, list3, "instances should be equal by `==` operator")
622+
}
588623
}
589624

590625
class ListStandaloneTests: ListTests {

0 commit comments

Comments
 (0)