diff --git a/IGListKit.xcodeproj/project.pbxproj b/IGListKit.xcodeproj/project.pbxproj index b7bf8bf6..6ad729dc 100644 --- a/IGListKit.xcodeproj/project.pbxproj +++ b/IGListKit.xcodeproj/project.pbxproj @@ -375,7 +375,7 @@ 88144F1B1D870EDC007C7F66 /* IGTestSingleItemDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 88144F021D870EDC007C7F66 /* IGTestSingleItemDataSource.m */; }; 88144F1D1D870EDC007C7F66 /* IGTestSupplementarySource.m in Sources */ = {isa = PBXBuildFile; fileRef = 88144F061D870EDC007C7F66 /* IGTestSupplementarySource.m */; }; 882BC1321E0118CB0083B311 /* IGTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 88144F001D870EDC007C7F66 /* IGTestObject.m */; }; - 883797082022304E00B94676 /* BuildFile in Headers */ = {isa = PBXBuildFile; }; + 883797082022304E00B94676 /* (null) in Headers */ = {isa = PBXBuildFile; }; 88379728202236AB00B94676 /* IGListAdapterUpdateTester.m in Sources */ = {isa = PBXBuildFile; fileRef = 294CDE621F995DD7002CF6E4 /* IGListAdapterUpdateTester.m */; }; 88379729202236AC00B94676 /* IGListAdapterUpdateTester.m in Sources */ = {isa = PBXBuildFile; fileRef = 294CDE621F995DD7002CF6E4 /* IGListAdapterUpdateTester.m */; }; 885FE1DD1DC51A0D009CE2B4 /* IGListKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 885FE1D41DC51A0D009CE2B4 /* IGListKit.framework */; }; @@ -418,6 +418,8 @@ E56B7B3420A9D7100071010C /* IGListCollectionScrollingTraitsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E56B7B3320A9D7100071010C /* IGListCollectionScrollingTraitsTests.m */; }; E56B7B3520A9D7100071010C /* IGListCollectionScrollingTraitsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E56B7B3320A9D7100071010C /* IGListCollectionScrollingTraitsTests.m */; }; E8D312E01FC472A60009FA2F /* IGListContentInsetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E8D312DF1FC472A60009FA2F /* IGListContentInsetTests.m */; }; + F102DBBB2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = F102DBBA2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m */; }; + F102DBBC2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = F102DBBA2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m */; }; F1855A4C29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; }; F1855A4D29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; }; F1855A4E29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; }; @@ -749,6 +751,7 @@ DD3152AC1DE227FA00AC9D2C /* IGListKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IGListKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E56B7B3320A9D7100071010C /* IGListCollectionScrollingTraitsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListCollectionScrollingTraitsTests.m; sourceTree = ""; }; E8D312DF1FC472A60009FA2F /* IGListContentInsetTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IGListContentInsetTests.m; sourceTree = ""; }; + F102DBBA2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListArrayUtilsInternal.m; sourceTree = ""; }; F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListDiffDescriptionStringTests.m; sourceTree = ""; }; F18CC75B29EFBB9400DC3B9A /* IGListCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListCollectionViewTests.m; sourceTree = ""; }; F18CC75E29EFBBB300DC3B9A /* IGListBindingSingleSectionControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListBindingSingleSectionControllerTests.m; sourceTree = ""; }; @@ -946,6 +949,7 @@ 7AD6864923A89E7F009000DE /* IGListAdapterUpdaterHelpers.m */, 7A02CF702361513400B49FAE /* IGListAdapterUpdaterInternal.h */, 7A02CF812361513500B49FAE /* IGListArrayUtilsInternal.h */, + F102DBBA2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m */, 7A02CF8C2361513500B49FAE /* IGListBatchUpdateData+DebugDescription.h */, 7A02CF7C2361513400B49FAE /* IGListBatchUpdateData+DebugDescription.m */, 7A02CF782361513400B49FAE /* IGListBatchUpdateState.h */, @@ -1436,7 +1440,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 883797082022304E00B94676 /* BuildFile in Headers */, + 883797082022304E00B94676 /* (null) in Headers */, 7A02D0C023615CE500B49FAE /* IGListKit.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1923,6 +1927,7 @@ 7A92EAB523A8A5FF00E5A13D /* IGListAdapterUpdaterHelpers.m in Sources */, 7A02CFD92361513600B49FAE /* IGListBatchUpdateData+DebugDescription.m in Sources */, 7A02CFAF2361513600B49FAE /* UICollectionViewLayout+InteractiveReordering.m in Sources */, + F102DBBC2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2041,6 +2046,7 @@ 7AD6864B23A89E7F009000DE /* IGListAdapterUpdaterHelpers.m in Sources */, 7A02CFD82361513600B49FAE /* IGListBatchUpdateData+DebugDescription.m in Sources */, 7A02CFAE2361513600B49FAE /* UICollectionViewLayout+InteractiveReordering.m in Sources */, + F102DBBB2ACE4CD500394DB7 /* IGListArrayUtilsInternal.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/IGListKit/Internal/IGListArrayUtilsInternal.h b/Source/IGListKit/Internal/IGListArrayUtilsInternal.h index a2411477..2e77e317 100644 --- a/Source/IGListKit/Internal/IGListArrayUtilsInternal.h +++ b/Source/IGListKit/Internal/IGListArrayUtilsInternal.h @@ -5,34 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef IGListArrayUtilsInternal_h -#define IGListArrayUtilsInternal_h +#import -#if !__has_include() -#import "IGListBatchUpdateData.h" -#else -#import -#endif +@protocol IGListDiffable; -static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray> *objects) { - if (objects == nil) { - return nil; - } - - NSMapTable *identifierMap = [NSMapTable strongToStrongObjectsMapTable]; - NSMutableArray *uniqueObjects = [NSMutableArray new]; - for (id object in objects) { - id diffIdentifier = [object diffIdentifier]; - id previousObject = [identifierMap objectForKey:diffIdentifier]; - if (diffIdentifier != nil - && previousObject == nil) { - [identifierMap setObject:object forKey:diffIdentifier]; - [uniqueObjects addObject:object]; - } else { - IGLKLog(@"Duplicate identifier %@ for object %@ with object %@", diffIdentifier, object, previousObject); - } - } - return uniqueObjects; -} - -#endif /* IGListArrayUtilsInternal_h */ +/// Returns a copy of the provided array, with all duplicates +/// of objects with the same `diffIdentifier` value removed. +/// - Parameter objects: The list of diffable objects to filter. +NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray> *objects); diff --git a/Source/IGListKit/Internal/IGListArrayUtilsInternal.m b/Source/IGListKit/Internal/IGListArrayUtilsInternal.m new file mode 100644 index 00000000..86736169 --- /dev/null +++ b/Source/IGListKit/Internal/IGListArrayUtilsInternal.m @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListArrayUtilsInternal.h" + +#if !__has_include() +#import "IGListBatchUpdateData.h" +#import "IGListDiffable.h" +#else +#import +#import +#endif + +NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray> *objects) { + if (objects == nil) { + return nil; + } + + NSMapTable *identifierMap = [NSMapTable strongToStrongObjectsMapTable]; + NSMutableArray *uniqueObjects = [NSMutableArray new]; + for (id object in objects) { + id diffIdentifier = [object diffIdentifier]; + id previousObject = [identifierMap objectForKey:diffIdentifier]; + if (diffIdentifier != nil + && previousObject == nil) { + [identifierMap setObject:object forKey:diffIdentifier]; + [uniqueObjects addObject:object]; + } else { + IGLKLog(@"Duplicate identifier %@ for object %@ with object %@", diffIdentifier, object, previousObject); + } + } + return uniqueObjects; +}