diff --git a/CHANGELOG.md b/CHANGELOG.md index ae7eacf9..6b9ff897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,8 @@ This release closes the [3.0.0 milestone](https://github.com/Instagram/IGListKit - Added `IGListGenericSectionController` to take advantage of Objective-C (and Swift) generics and automatically store strongly-typed references to the object powering your section controller. [Ryan Nystrom](https://github.com/rnystrom) (tbd) +- Added a debug option for IGListKit that you can print to lldb via `po [IGListDebugger dump]`. [Ryan Nystrom](https://github.com/rnystrom) [(#617)](https://github.com/Instagram/IGListKit/pull/617) + ### Fixes - Gracefully handle a `nil` section controller returned by an `IGListAdapterDataSource`. [Ryan Nystrom](https://github.com/rnystrom) [(#488)](https://github.com/Instagram/IGListKit/pull/488) diff --git a/IGListKit.xcodeproj/project.pbxproj b/IGListKit.xcodeproj/project.pbxproj index ce07b8c5..e72c0385 100644 --- a/IGListKit.xcodeproj/project.pbxproj +++ b/IGListKit.xcodeproj/project.pbxproj @@ -157,6 +157,21 @@ 1F2984CA1E8039EC005FA211 /* IGListCollectionViewLayoutInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 917E89871E800EE70015F934 /* IGListCollectionViewLayoutInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; 26271C8A1DAE94E40073E116 /* IGTestSingleNibItemDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 26271C891DAE94E40073E116 /* IGTestSingleNibItemDataSource.m */; }; 26271C8C1DAE96740073E116 /* IGListSingleNibItemControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 26271C8B1DAE96740073E116 /* IGListSingleNibItemControllerTests.m */; }; + 290DF3541E930C89009FE456 /* IGListDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3521E930C89009FE456 /* IGListDebugger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3551E930C89009FE456 /* IGListDebugger.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3531E930C89009FE456 /* IGListDebugger.m */; }; + 290DF3581E930CE2009FE456 /* UICollectionView+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3561E930CE2009FE456 /* UICollectionView+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3591E930CE2009FE456 /* UICollectionView+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3571E930CE2009FE456 /* UICollectionView+DebugDescription.m */; }; + 290DF35C1E930CED009FE456 /* IGListAdapter+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF35A1E930CED009FE456 /* IGListAdapter+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF35D1E930CED009FE456 /* IGListAdapter+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF35B1E930CED009FE456 /* IGListAdapter+DebugDescription.m */; }; + 290DF3601E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF35E1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3611E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF35F1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m */; }; + 290DF3641E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3621E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3651E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3631E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m */; }; + 290DF3701E931457009FE456 /* IGListSectionMap+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF36E1E931457009FE456 /* IGListSectionMap+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3711E931457009FE456 /* IGListSectionMap+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF36F1E931457009FE456 /* IGListSectionMap+DebugDescription.m */; }; + 290DF3741E931B57009FE456 /* IGListDebuggingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3721E931B57009FE456 /* IGListDebuggingUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 290DF3751E931B57009FE456 /* IGListDebuggingUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3731E931B57009FE456 /* IGListDebuggingUtilities.m */; }; + 290DF3771E9323E6009FE456 /* IGListDebuggerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3761E9323E6009FE456 /* IGListDebuggerTests.m */; }; 2914BEE91DCD15F400C96401 /* IGTestNibSupplementaryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2904861C1DCD02140007F41D /* IGTestNibSupplementaryView.xib */; }; 2914BEEA1DCD15F400C96401 /* IGTestNibSupplementaryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2904861C1DCD02140007F41D /* IGTestNibSupplementaryView.xib */; }; 292658551E7498220041B56D /* IGListKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B3B928B1E08D7F5008390ED /* IGListKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -167,6 +182,20 @@ 292658711E75E2440041B56D /* IGListBatchUpdateState.h in Headers */ = {isa = PBXBuildFile; fileRef = 297278C31E6B59D50099D8EA /* IGListBatchUpdateState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 292807391E82CE240077A81C /* IGListBatchContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 292807381E82CE240077A81C /* IGListBatchContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2928073A1E82CE2E0077A81C /* IGListBatchContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 292807381E82CE240077A81C /* IGListBatchContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 294652AF1EA927440063BDD9 /* IGListAdapter+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF35B1E930CED009FE456 /* IGListAdapter+DebugDescription.m */; }; + 294652B01EA927440063BDD9 /* IGListAdapterUpdater+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3631E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m */; }; + 294652B11EA927440063BDD9 /* IGListBatchUpdateData+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF35F1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m */; }; + 294652B21EA927440063BDD9 /* IGListDebugger.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3531E930C89009FE456 /* IGListDebugger.m */; }; + 294652B31EA927440063BDD9 /* IGListSectionMap+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF36F1E931457009FE456 /* IGListSectionMap+DebugDescription.m */; }; + 294652B41EA927440063BDD9 /* UICollectionView+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3571E930CE2009FE456 /* UICollectionView+DebugDescription.m */; }; + 294652B51EA9275A0063BDD9 /* IGListDebuggingUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 290DF3731E931B57009FE456 /* IGListDebuggingUtilities.m */; }; + 294652B61EA927750063BDD9 /* IGListAdapter+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF35A1E930CED009FE456 /* IGListAdapter+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652B71EA927750063BDD9 /* IGListAdapterUpdater+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3621E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652B81EA927750063BDD9 /* IGListBatchUpdateData+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF35E1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652B91EA927750063BDD9 /* IGListDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3521E930C89009FE456 /* IGListDebugger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652BA1EA927750063BDD9 /* IGListDebuggingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3721E931B57009FE456 /* IGListDebuggingUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652BB1EA927750063BDD9 /* IGListSectionMap+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF36E1E931457009FE456 /* IGListSectionMap+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 294652BC1EA927750063BDD9 /* UICollectionView+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 290DF3561E930CE2009FE456 /* UICollectionView+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; 294AC6321DDE4C19002FCE5D /* IGListDiffResultTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 294AC6311DDE4C19002FCE5D /* IGListDiffResultTests.m */; }; 296AC95C1EA518D3005137E2 /* IGListReloadIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 296AC95A1EA518D3005137E2 /* IGListReloadIndexPath.h */; settings = {ATTRIBUTES = (Private, ); }; }; 296AC95D1EA518D3005137E2 /* IGListReloadIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 296AC95A1EA518D3005137E2 /* IGListReloadIndexPath.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -405,6 +434,21 @@ 2904861C1DCD02140007F41D /* IGTestNibSupplementaryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IGTestNibSupplementaryView.xib; sourceTree = ""; }; 2904861E1DCD02750007F41D /* IGTestNibSupplementaryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGTestNibSupplementaryView.h; sourceTree = ""; }; 2904861F1DCD02750007F41D /* IGTestNibSupplementaryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGTestNibSupplementaryView.m; sourceTree = ""; }; + 290DF3521E930C89009FE456 /* IGListDebugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListDebugger.h; sourceTree = ""; }; + 290DF3531E930C89009FE456 /* IGListDebugger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListDebugger.m; sourceTree = ""; }; + 290DF3561E930CE2009FE456 /* UICollectionView+DebugDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+DebugDescription.h"; sourceTree = ""; }; + 290DF3571E930CE2009FE456 /* UICollectionView+DebugDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionView+DebugDescription.m"; sourceTree = ""; }; + 290DF35A1E930CED009FE456 /* IGListAdapter+DebugDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListAdapter+DebugDescription.h"; sourceTree = ""; }; + 290DF35B1E930CED009FE456 /* IGListAdapter+DebugDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListAdapter+DebugDescription.m"; sourceTree = ""; }; + 290DF35E1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListBatchUpdateData+DebugDescription.h"; sourceTree = ""; }; + 290DF35F1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListBatchUpdateData+DebugDescription.m"; sourceTree = ""; }; + 290DF3621E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListAdapterUpdater+DebugDescription.h"; sourceTree = ""; }; + 290DF3631E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListAdapterUpdater+DebugDescription.m"; sourceTree = ""; }; + 290DF36E1E931457009FE456 /* IGListSectionMap+DebugDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListSectionMap+DebugDescription.h"; sourceTree = ""; }; + 290DF36F1E931457009FE456 /* IGListSectionMap+DebugDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListSectionMap+DebugDescription.m"; sourceTree = ""; }; + 290DF3721E931B57009FE456 /* IGListDebuggingUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListDebuggingUtilities.h; sourceTree = ""; }; + 290DF3731E931B57009FE456 /* IGListDebuggingUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListDebuggingUtilities.m; sourceTree = ""; }; + 290DF3761E9323E6009FE456 /* IGListDebuggerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListDebuggerTests.m; sourceTree = ""; }; 2926586B1E75E01A0041B56D /* IGListBindingSectionControllerDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListBindingSectionControllerDataSource.h; sourceTree = ""; }; 2926586E1E75E0830041B56D /* IGListBindingSectionControllerSelectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListBindingSectionControllerSelectionDelegate.h; sourceTree = ""; }; 292807381E82CE240077A81C /* IGListBatchContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListBatchContext.h; sourceTree = ""; }; @@ -657,16 +701,26 @@ 0B3B92B51E08D7F5008390ED /* Internal */ = { isa = PBXGroup; children = ( + 290DF35A1E930CED009FE456 /* IGListAdapter+DebugDescription.h */, + 290DF35B1E930CED009FE456 /* IGListAdapter+DebugDescription.m */, DA5F48491E8E9D7000DAE6DA /* IGListAdapter+UICollectionView.h */, DA5F484A1E8E9D7000DAE6DA /* IGListAdapter+UICollectionView.m */, 0B3B92B61E08D7F5008390ED /* IGListAdapterInternal.h */, 0B3B92B71E08D7F5008390ED /* IGListAdapterProxy.h */, 0B3B92B81E08D7F5008390ED /* IGListAdapterProxy.m */, + 290DF3621E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h */, + 290DF3631E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m */, 0B3B92B91E08D7F5008390ED /* IGListAdapterUpdaterInternal.h */, + 290DF35E1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h */, + 290DF35F1E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m */, 297278BB1E6B58560099D8EA /* IGListBatchUpdates.h */, 297278BC1E6B58560099D8EA /* IGListBatchUpdates.m */, 297278C31E6B59D50099D8EA /* IGListBatchUpdateState.h */, 917E89871E800EE70015F934 /* IGListCollectionViewLayoutInternal.h */, + 290DF3521E930C89009FE456 /* IGListDebugger.h */, + 290DF3531E930C89009FE456 /* IGListDebugger.m */, + 290DF3721E931B57009FE456 /* IGListDebuggingUtilities.h */, + 290DF3731E931B57009FE456 /* IGListDebuggingUtilities.m */, 0B3B92BA1E08D7F5008390ED /* IGListDisplayHandler.h */, 0B3B92BB1E08D7F5008390ED /* IGListDisplayHandler.m */, 296AC95A1EA518D3005137E2 /* IGListReloadIndexPath.h */, @@ -674,9 +728,13 @@ 0B3B92BC1E08D7F5008390ED /* IGListSectionControllerInternal.h */, 0B3B92BD1E08D7F5008390ED /* IGListSectionMap.h */, 0B3B92BE1E08D7F5008390ED /* IGListSectionMap.m */, + 290DF36E1E931457009FE456 /* IGListSectionMap+DebugDescription.h */, + 290DF36F1E931457009FE456 /* IGListSectionMap+DebugDescription.m */, 0B3B92BF1E08D7F5008390ED /* IGListStackedSectionControllerInternal.h */, 0B3B92C01E08D7F5008390ED /* IGListWorkingRangeHandler.h */, 0B3B92C11E08D7F5008390ED /* IGListWorkingRangeHandler.mm */, + 290DF3561E930CE2009FE456 /* UICollectionView+DebugDescription.h */, + 290DF3571E930CE2009FE456 /* UICollectionView+DebugDescription.m */, 0B3B92C21E08D7F5008390ED /* UICollectionView+IGListBatchUpdateData.h */, 0B3B92C31E08D7F5008390ED /* UICollectionView+IGListBatchUpdateData.m */, ); @@ -810,6 +868,7 @@ 88144EE51D870EDC007C7F66 /* IGListBatchUpdateDataTests.m */, 298DD9CD1E3ADD1400F76F50 /* IGListBindingSectionControllerTests.m */, 298DDA231E3B15EE00F76F50 /* IGListCollectionViewLayoutTests.m */, + 290DF3761E9323E6009FE456 /* IGListDebuggerTests.m */, 294AC6311DDE4C19002FCE5D /* IGListDiffResultTests.m */, 88144EE61D870EDC007C7F66 /* IGListDiffSwiftTests.swift */, 88144EE81D870EDC007C7F66 /* IGListDiffTests.m */, @@ -860,11 +919,14 @@ 2926586D1E75E01A0041B56D /* IGListBindingSectionControllerDataSource.h in Headers */, 0B3B92C71E08D7F5008390ED /* IGListBatchUpdateData.h in Headers */, 0B3B92ED1E08D7F5008390ED /* IGListMoveIndexPathInternal.h in Headers */, + 294652BA1EA927750063BDD9 /* IGListDebuggingUtilities.h in Headers */, 0B3B93351E08D7F5008390ED /* IGListDisplayHandler.h in Headers */, 0B3B92D31E08D7F5008390ED /* IGListIndexPathResult.h in Headers */, 0B3B93251E08D7F5008390ED /* IGListSupplementaryViewSource.h in Headers */, 0B3B92F31E08D7F5008390ED /* NSString+IGListDiffable.h in Headers */, 0B3B932D1E08D7F5008390ED /* IGListAdapterInternal.h in Headers */, + 294652BB1EA927750063BDD9 /* IGListSectionMap+DebugDescription.h in Headers */, + 294652BC1EA927750063BDD9 /* UICollectionView+DebugDescription.h in Headers */, 0B3B93291E08D7F5008390ED /* IGListWorkingRangeDelegate.h in Headers */, 0B3B92C51E08D7F5008390ED /* IGListAssert.h in Headers */, 0B3B93051E08D7F5008390ED /* IGListCollectionContext.h in Headers */, @@ -877,9 +939,12 @@ 0B3B93391E08D7F5008390ED /* IGListSectionControllerInternal.h in Headers */, 0B3B92DB1E08D7F5008390ED /* IGListKit.h in Headers */, 0B3B93031E08D7F5008390ED /* IGListAdapterUpdaterDelegate.h in Headers */, + 294652B91EA927750063BDD9 /* IGListDebugger.h in Headers */, + 294652B71EA927750063BDD9 /* IGListAdapterUpdater+DebugDescription.h in Headers */, 0B3B92CB1E08D7F5008390ED /* IGListDiff.h in Headers */, 0B3B933B1E08D7F5008390ED /* IGListSectionMap.h in Headers */, 0B3B92DF1E08D7F5008390ED /* IGListMoveIndex.h in Headers */, + 294652B61EA927750063BDD9 /* IGListAdapter+DebugDescription.h in Headers */, 0B3B92CF1E08D7F5008390ED /* IGListDiffable.h in Headers */, 29DA5CA41EA7C75500113926 /* IGListGenericSectionController.h in Headers */, 0B3B92EB1E08D7F5008390ED /* IGListMoveIndexInternal.h in Headers */, @@ -887,6 +952,7 @@ 0B3B92EF1E08D7F5008390ED /* NSNumber+IGListDiffable.h in Headers */, 298DD9C81E3ACFE300F76F50 /* IGListBindingSectionController.h in Headers */, 0B3B93411E08D7F5008390ED /* IGListWorkingRangeHandler.h in Headers */, + 294652B81EA927750063BDD9 /* IGListBatchUpdateData+DebugDescription.h in Headers */, 0B3B92E71E08D7F5008390ED /* IGListIndexPathResultInternal.h in Headers */, 0B3B932F1E08D7F5008390ED /* IGListAdapterProxy.h in Headers */, 0B3B92FD1E08D7F5008390ED /* IGListAdapterDelegate.h in Headers */, @@ -909,27 +975,32 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 290DF3541E930C89009FE456 /* IGListDebugger.h in Headers */, 989317631E0ED45900DB93B3 /* IGListCompatibility.h in Headers */, 0B3B92FA1E08D7F5008390ED /* IGListAdapterDataSource.h in Headers */, 0B3B92E81E08D7F5008390ED /* IGListIndexSetResultInternal.h in Headers */, 0B3B930A1E08D7F5008390ED /* IGListDisplayDelegate.h in Headers */, 0B3B933E1E08D7F5008390ED /* IGListStackedSectionControllerInternal.h in Headers */, + 290DF3641E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.h in Headers */, 0B3B93161E08D7F5008390ED /* IGListSectionController.h in Headers */, 0B3B93441E08D7F5008390ED /* UICollectionView+IGListBatchUpdateData.h in Headers */, 0B3B92DC1E08D7F5008390ED /* IGListMacros.h in Headers */, 0B3B92D61E08D7F5008390ED /* IGListIndexSetResult.h in Headers */, 0B3B92C61E08D7F5008390ED /* IGListBatchUpdateData.h in Headers */, + 290DF3741E931B57009FE456 /* IGListDebuggingUtilities.h in Headers */, 0B3B92EC1E08D7F5008390ED /* IGListMoveIndexPathInternal.h in Headers */, 0B3B93341E08D7F5008390ED /* IGListDisplayHandler.h in Headers */, 0B3B92D21E08D7F5008390ED /* IGListIndexPathResult.h in Headers */, 2926586C1E75E01A0041B56D /* IGListBindingSectionControllerDataSource.h in Headers */, 0B3B93241E08D7F5008390ED /* IGListSupplementaryViewSource.h in Headers */, + 290DF3701E931457009FE456 /* IGListSectionMap+DebugDescription.h in Headers */, 0B3B92F21E08D7F5008390ED /* NSString+IGListDiffable.h in Headers */, 0B3B932C1E08D7F5008390ED /* IGListAdapterInternal.h in Headers */, 0B3B93281E08D7F5008390ED /* IGListWorkingRangeDelegate.h in Headers */, 0B3B92C41E08D7F5008390ED /* IGListAssert.h in Headers */, 0B3B93041E08D7F5008390ED /* IGListCollectionContext.h in Headers */, 0B3B931C1E08D7F5008390ED /* IGListSingleSectionController.h in Headers */, + 290DF3601E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.h in Headers */, 0B3B92D01E08D7F5008390ED /* IGListExperiments.h in Headers */, 296AC95C1EA518D3005137E2 /* IGListReloadIndexPath.h in Headers */, 0B3B93321E08D7F5008390ED /* IGListAdapterUpdaterInternal.h in Headers */, @@ -941,6 +1012,7 @@ 0B3B92CA1E08D7F5008390ED /* IGListDiff.h in Headers */, 0B3B933A1E08D7F5008390ED /* IGListSectionMap.h in Headers */, 0B3B92DE1E08D7F5008390ED /* IGListMoveIndex.h in Headers */, + 290DF35C1E930CED009FE456 /* IGListAdapter+DebugDescription.h in Headers */, 0B3B92CE1E08D7F5008390ED /* IGListDiffable.h in Headers */, 29DA5CA01EA7C70400113926 /* IGListGenericSectionController.h in Headers */, 0B3B92EA1E08D7F5008390ED /* IGListMoveIndexInternal.h in Headers */, @@ -962,6 +1034,7 @@ 297278BD1E6B58560099D8EA /* IGListBatchUpdates.h in Headers */, 0B3B92FE1E08D7F5008390ED /* IGListAdapterUpdater.h in Headers */, 0B3B93141E08D7F5008390ED /* IGListScrollDelegate.h in Headers */, + 290DF3581E930CE2009FE456 /* UICollectionView+DebugDescription.h in Headers */, 0B3B93261E08D7F5008390ED /* IGListUpdatingDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1318,26 +1391,33 @@ 0B3B92F51E08D7F5008390ED /* NSString+IGListDiffable.m in Sources */, 0B3B93011E08D7F5008390ED /* IGListAdapterUpdater.m in Sources */, 29DA5CA51EA7C75500113926 /* IGListGenericSectionController.m in Sources */, + 294652B31EA927440063BDD9 /* IGListSectionMap+DebugDescription.m in Sources */, 0B3B92D91E08D7F5008390ED /* IGListIndexSetResult.m in Sources */, + 294652AF1EA927440063BDD9 /* IGListAdapter+DebugDescription.m in Sources */, 0B3B93431E08D7F5008390ED /* IGListWorkingRangeHandler.mm in Sources */, 0B3B92F11E08D7F5008390ED /* NSNumber+IGListDiffable.m in Sources */, 298DDA221E3B0DC800F76F50 /* IGListCollectionViewLayout.mm in Sources */, + 294652B51EA9275A0063BDD9 /* IGListDebuggingUtilities.m in Sources */, 0B3B93311E08D7F5008390ED /* IGListAdapterProxy.m in Sources */, + 294652B01EA927440063BDD9 /* IGListAdapterUpdater+DebugDescription.m in Sources */, 0B3B92CD1E08D7F5008390ED /* IGListDiff.mm in Sources */, 297278C11E6B58560099D8EA /* IGListBatchUpdates.m in Sources */, 0B3B931F1E08D7F5008390ED /* IGListSingleSectionController.m in Sources */, 296AC9601EA518D3005137E2 /* IGListReloadIndexPath.m in Sources */, + 294652B21EA927440063BDD9 /* IGListDebugger.m in Sources */, 0B3B92D51E08D7F5008390ED /* IGListIndexPathResult.m in Sources */, 0B3B93371E08D7F5008390ED /* IGListDisplayHandler.m in Sources */, 0B3B92E11E08D7F5008390ED /* IGListMoveIndex.m in Sources */, 0B3B93471E08D7F5008390ED /* UICollectionView+IGListBatchUpdateData.m in Sources */, 0B3B92E51E08D7F5008390ED /* IGListMoveIndexPath.m in Sources */, DAA83ACF1E8ECE06000F6810 /* IGListAdapter+UICollectionView.m in Sources */, + 294652B11EA927440063BDD9 /* IGListBatchUpdateData+DebugDescription.m in Sources */, 0B3B933D1E08D7F5008390ED /* IGListSectionMap.m in Sources */, 0B3B92F91E08D7F5008390ED /* IGListAdapter.m in Sources */, 0B3B93191E08D7F5008390ED /* IGListSectionController.m in Sources */, 0B3B93131E08D7F5008390ED /* IGListReloadDataUpdater.m in Sources */, 0B3B93231E08D7F5008390ED /* IGListStackedSectionController.m in Sources */, + 294652B41EA927440063BDD9 /* UICollectionView+DebugDescription.m in Sources */, 298DD9CB1E3ACFE300F76F50 /* IGListBindingSectionController.m in Sources */, 0B3B92C91E08D7F5008390ED /* IGListBatchUpdateData.mm in Sources */, ); @@ -1406,28 +1486,35 @@ buildActionMask = 2147483647; files = ( 0B3B92F41E08D7F5008390ED /* NSString+IGListDiffable.m in Sources */, + 290DF3591E930CE2009FE456 /* UICollectionView+DebugDescription.m in Sources */, 0B3B93001E08D7F5008390ED /* IGListAdapterUpdater.m in Sources */, 29DA5CA11EA7C70400113926 /* IGListGenericSectionController.m in Sources */, + 290DF3711E931457009FE456 /* IGListSectionMap+DebugDescription.m in Sources */, 0B3B92D81E08D7F5008390ED /* IGListIndexSetResult.m in Sources */, 0B3B93421E08D7F5008390ED /* IGListWorkingRangeHandler.mm in Sources */, 0B3B92F01E08D7F5008390ED /* NSNumber+IGListDiffable.m in Sources */, 298DDA211E3B0DC800F76F50 /* IGListCollectionViewLayout.mm in Sources */, 0B3B93301E08D7F5008390ED /* IGListAdapterProxy.m in Sources */, 0B3B92CC1E08D7F5008390ED /* IGListDiff.mm in Sources */, + 290DF3651E930D25009FE456 /* IGListAdapterUpdater+DebugDescription.m in Sources */, 297278BF1E6B58560099D8EA /* IGListBatchUpdates.m in Sources */, + 290DF3751E931B57009FE456 /* IGListDebuggingUtilities.m in Sources */, 0B3B931E1E08D7F5008390ED /* IGListSingleSectionController.m in Sources */, 296AC95F1EA518D3005137E2 /* IGListReloadIndexPath.m in Sources */, 0B3B92D41E08D7F5008390ED /* IGListIndexPathResult.m in Sources */, 0B3B93361E08D7F5008390ED /* IGListDisplayHandler.m in Sources */, 0B3B92E01E08D7F5008390ED /* IGListMoveIndex.m in Sources */, 0B3B93461E08D7F5008390ED /* UICollectionView+IGListBatchUpdateData.m in Sources */, + 290DF3551E930C89009FE456 /* IGListDebugger.m in Sources */, 0B3B92E41E08D7F5008390ED /* IGListMoveIndexPath.m in Sources */, DA5F484C1E8E9D7000DAE6DA /* IGListAdapter+UICollectionView.m in Sources */, 0B3B933C1E08D7F5008390ED /* IGListSectionMap.m in Sources */, 0B3B92F81E08D7F5008390ED /* IGListAdapter.m in Sources */, 0B3B93181E08D7F5008390ED /* IGListSectionController.m in Sources */, + 290DF3611E930D05009FE456 /* IGListBatchUpdateData+DebugDescription.m in Sources */, 0B3B93121E08D7F5008390ED /* IGListReloadDataUpdater.m in Sources */, 0B3B93221E08D7F5008390ED /* IGListStackedSectionController.m in Sources */, + 290DF35D1E930CED009FE456 /* IGListAdapter+DebugDescription.m in Sources */, 298DD9CA1E3ACFE300F76F50 /* IGListBindingSectionController.m in Sources */, 0B3B92C81E08D7F5008390ED /* IGListBatchUpdateData.mm in Sources */, ); @@ -1440,6 +1527,7 @@ 298DDA391E3B168F00F76F50 /* IGLayoutTestItem.m in Sources */, 88144F1C1D870EDC007C7F66 /* IGTestStackedDataSource.m in Sources */, 88144F181D870EDC007C7F66 /* IGTestDelegateController.m in Sources */, + 290DF3771E9323E6009FE456 /* IGListDebuggerTests.m in Sources */, 298DDA3A1E3B16F600F76F50 /* IGLayoutTestDataSource.m in Sources */, 88144F0D1D870EDC007C7F66 /* IGListDisplayHandlerTests.m in Sources */, 298DDA141E3AE3F300F76F50 /* IGTestDiffingDataSource.m in Sources */, diff --git a/Source/Common/IGListMacros.h b/Source/Common/IGListMacros.h index 23c3b1ff..b464be3a 100644 --- a/Source/Common/IGListMacros.h +++ b/Source/Common/IGListMacros.h @@ -24,3 +24,7 @@ #else #define IGLKLog( s, ... ) #endif + +#ifndef IGLK_DEBUG_DESCRIPTION_ENABLED +#define IGLK_DEBUG_DESCRIPTION_ENABLED DEBUG +#endif // #ifndef IGLK_DEBUG_DESCRIPTION_ENABLED diff --git a/Source/IGListAdapter.m b/Source/IGListAdapter.m index 4382bac9..791f1459 100644 --- a/Source/IGListAdapter.m +++ b/Source/IGListAdapter.m @@ -14,6 +14,7 @@ #import #import "IGListSectionControllerInternal.h" +#import "IGListDebugger.h" @implementation IGListAdapter { NSMapTable *_viewSectionControllerMap; @@ -51,6 +52,8 @@ _updater = updater; _viewController = viewController; + + [IGListDebugger trackAdapter:self]; } return self; } diff --git a/Source/IGListAdapterUpdater.m b/Source/IGListAdapterUpdater.m index 16d46ff3..75003eec 100644 --- a/Source/IGListAdapterUpdater.m +++ b/Source/IGListAdapterUpdater.m @@ -155,6 +155,7 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray + +@interface IGListAdapter (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/Source/Internal/IGListAdapter+DebugDescription.m b/Source/Internal/IGListAdapter+DebugDescription.m new file mode 100644 index 00000000..60b4fdb7 --- /dev/null +++ b/Source/Internal/IGListAdapter+DebugDescription.m @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListAdapter+DebugDescription.h" + +#import "IGListAdapterInternal.h" +#import "IGListSectionMap+DebugDescription.h" +#import "IGListAdapterUpdater+DebugDescription.h" +#import "UICollectionView+DebugDescription.h" +#import "IGListDebuggingUtilities.h" + +@implementation IGListAdapter (DebugDescription) + +- (NSString *)debugDescription { + NSMutableArray *lines = [NSMutableArray arrayWithObject:[NSString stringWithFormat:@"IGListAdapter %p:", self]]; + [lines addObjectsFromArray:IGListDebugIndentedLines([self debugDescriptionLines])]; + return [lines componentsJoinedByString:@"\n"]; +} + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Updater type: %@", NSStringFromClass(self.updater.class)]]; + [debug addObject:[NSString stringWithFormat:@"Data source: %@", self.dataSource]]; + [debug addObject:[NSString stringWithFormat:@"Collection view delegate: %@", self.collectionViewDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Scroll view delegate: %@", self.scrollViewDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Is in update block: %@", IGListDebugBOOL(self.isInUpdateBlock)]]; + [debug addObject:[NSString stringWithFormat:@"View controller: %@", self.viewController]]; + + if (self.registeredCellClasses.count > 0) { + [debug addObject:@"Registered cell classes:"]; + [debug addObject:[self.registeredCellClasses description]]; + } + + if (self.registeredNibNames.count > 0) { + [debug addObject:@"Registered nib names:"]; + [debug addObject:[self.registeredNibNames description]]; + } + + if (self.registeredSupplementaryViewIdentifiers.count > 0) { + [debug addObject:@"Registered supplementary view identifiers:"]; + [debug addObject:[self.registeredSupplementaryViewIdentifiers description]]; + } + + if (self.registeredSupplementaryViewNibNames.count > 0) { + [debug addObject:@"Registered supplementary view nib names:"]; + [debug addObject:self.registeredSupplementaryViewNibNames]; + } + + if ([self.updater isKindOfClass:[IGListAdapterUpdater class]]) { + [debug addObject:[NSString stringWithFormat:@"IGListAdapterUpdater instance %p:", self.updater]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([(IGListAdapterUpdater *)self.updater debugDescriptionLines])]; + } + + [debug addObject:[NSString stringWithFormat:@"Section map details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.sectionMap debugDescriptionLines])]; + + if (self.previousSectionMap != nil) { + [debug addObject:[NSString stringWithFormat:@"Previous section map details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.previousSectionMap debugDescriptionLines])]; + } + + [debug addObject:[NSString stringWithFormat:@"Collection view details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.collectionView debugDescriptionLines])]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/Source/Internal/IGListAdapterUpdater+DebugDescription.h b/Source/Internal/IGListAdapterUpdater+DebugDescription.h new file mode 100644 index 00000000..07d0fcf6 --- /dev/null +++ b/Source/Internal/IGListAdapterUpdater+DebugDescription.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface IGListAdapterUpdater (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/Source/Internal/IGListAdapterUpdater+DebugDescription.m b/Source/Internal/IGListAdapterUpdater+DebugDescription.m new file mode 100644 index 00000000..22553d40 --- /dev/null +++ b/Source/Internal/IGListAdapterUpdater+DebugDescription.m @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListAdapterUpdater+DebugDescription.h" + +#import "IGListAdapterUpdaterInternal.h" +#import "IGListBatchUpdateData+DebugDescription.h" +#import "IGListDebuggingUtilities.h" + +#if IGLK_DEBUG_DESCRIPTION_ENABLED +static NSMutableArray *linesFromObjects(NSArray *objects) { + NSMutableArray *lines = [NSMutableArray new]; + for (id object in objects) { + [lines addObject:[NSString stringWithFormat:@"Object %p of type %@ with identifier %@", + object, NSStringFromClass([object class]), [object diffIdentifier]]]; + } + return lines; +} +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + +@implementation IGListAdapterUpdater (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Moves as deletes+inserts: %@", IGListDebugBOOL(self.movesAsDeletesInserts)]]; + [debug addObject:[NSString stringWithFormat:@"Allows background reloading: %@", IGListDebugBOOL(self.allowsBackgroundReloading)]]; + [debug addObject:[NSString stringWithFormat:@"Has queued reload data: %@", IGListDebugBOOL(self.hasQueuedReloadData)]]; + [debug addObject:[NSString stringWithFormat:@"Queued update is animated: %@", IGListDebugBOOL(self.queuedUpdateIsAnimated)]]; + + NSString *stateString; + switch (self.state) { + case IGListBatchUpdateStateIdle: + stateString = @"Idle"; + break; + case IGListBatchUpdateStateQueuedBatchUpdate: + stateString = @"Queued batch update"; + break; + case IGListBatchUpdateStateExecutedBatchUpdateBlock: + stateString = @"Executed batch update block"; + break; + case IGListBatchUpdateStateExecutingBatchUpdateBlock: + stateString = @"Executing batch update block"; + break; + } + [debug addObject:[NSString stringWithFormat:@"State: %@", stateString]]; + + if (self.applyingUpdateData != nil) { + [debug addObject:@"Batch update data:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.applyingUpdateData debugDescriptionLines])]; + } + + if (self.fromObjects != nil) { + [debug addObject:@"From objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.fromObjects))]; + } + + if (self.toObjects != nil) { + [debug addObject:@"To objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.toObjects))]; + } + + if (self.pendingTransitionToObjects != nil) { + [debug addObject:@"Pending objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.pendingTransitionToObjects))]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/Source/Internal/IGListAdapterUpdaterInternal.h b/Source/Internal/IGListAdapterUpdaterInternal.h index 9de37264..6295c1f0 100644 --- a/Source/Internal/IGListAdapterUpdaterInternal.h +++ b/Source/Internal/IGListAdapterUpdaterInternal.h @@ -41,6 +41,7 @@ FOUNDATION_EXTERN void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, @property (nonatomic, assign, getter=hasQueuedReloadData) BOOL queuedReloadData; @property (nonatomic, assign) IGListBatchUpdateState state; +@property (nonatomic, strong, nullable) IGListBatchUpdateData *applyingUpdateData; - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView; - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView; diff --git a/Source/Internal/IGListBatchUpdateData+DebugDescription.h b/Source/Internal/IGListBatchUpdateData+DebugDescription.h new file mode 100644 index 00000000..a77072a9 --- /dev/null +++ b/Source/Internal/IGListBatchUpdateData+DebugDescription.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface IGListBatchUpdateData (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/Source/Internal/IGListBatchUpdateData+DebugDescription.m b/Source/Internal/IGListBatchUpdateData+DebugDescription.m new file mode 100644 index 00000000..bdf703cd --- /dev/null +++ b/Source/Internal/IGListBatchUpdateData+DebugDescription.m @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListBatchUpdateData+DebugDescription.h" + +@implementation IGListBatchUpdateData (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Insert sections: %@", self.insertSections]]; + [debug addObject:[NSString stringWithFormat:@"Delete sections: %@", self.deleteSections]]; + + for (IGListMoveIndex *move in self.moveSections) { + [debug addObject:[NSString stringWithFormat:@"Move from section %zi to %zi", move.from, move.to]]; + } + + for (NSIndexPath *path in self.deleteIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Delete section %zi item %zi", path.section, path.item]]; + } + + for (NSIndexPath *path in self.insertIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Insert section %zi item %zi", path.section, path.item]]; + } + + for (IGListMoveIndexPath *move in self.moveIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Move from section %zi item %zi to section %zi item %zi", + move.from.section, move.from.item, move.to.section, move.to.item]]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/Source/Internal/IGListDebugger.h b/Source/Internal/IGListDebugger.h new file mode 100644 index 00000000..dcd2086e --- /dev/null +++ b/Source/Internal/IGListDebugger.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +@class IGListAdapter; + +IGLK_SUBCLASSING_RESTRICTED +@interface IGListDebugger : NSObject + ++ (void)trackAdapter:(IGListAdapter *)adapter; + ++ (NSArray *)adapterDescriptions; + ++ (NSString *)dump; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end diff --git a/Source/Internal/IGListDebugger.m b/Source/Internal/IGListDebugger.m new file mode 100644 index 00000000..4368aff5 --- /dev/null +++ b/Source/Internal/IGListDebugger.m @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListDebugger.h" + +#import "IGListDebuggingUtilities.h" +#import "IGListAdapter+DebugDescription.h" + +@implementation IGListDebugger + +static NSHashTable *livingAdaptersTable = nil; + ++ (void)trackAdapter:(IGListAdapter *)adapter { +#if IGLK_DEBUG_DESCRIPTION_ENABLED + if (livingAdaptersTable == nil) { + livingAdaptersTable = [NSHashTable weakObjectsHashTable]; + } + [livingAdaptersTable addObject:adapter]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED +} + ++ (NSArray *)adapterDescriptions { + NSMutableArray *descriptions = [NSMutableArray new]; + for (IGListAdapter *adapter in livingAdaptersTable) { + [descriptions addObject:[adapter debugDescription]]; + } + return descriptions; +} + ++ (NSString *)dump { + return [[self adapterDescriptions] componentsJoinedByString:@"\n"]; +} + +@end diff --git a/Source/Internal/IGListDebuggingUtilities.h b/Source/Internal/IGListDebuggingUtilities.h new file mode 100644 index 00000000..96fce2ec --- /dev/null +++ b/Source/Internal/IGListDebuggingUtilities.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@class IGListAdapter; + +extern NSString *IGListDebugBOOL(BOOL b); + +extern NSArray *IGListDebugIndentedLines(NSArray *lines); diff --git a/Source/Internal/IGListDebuggingUtilities.m b/Source/Internal/IGListDebuggingUtilities.m new file mode 100644 index 00000000..764430c4 --- /dev/null +++ b/Source/Internal/IGListDebuggingUtilities.m @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListDebuggingUtilities.h" + +NSString *IGListDebugBOOL(BOOL b) { + return b ? @"Yes" : @"No"; +} + +NSArray *IGListDebugIndentedLines(NSArray *lines) { + NSMutableArray *newLines = [NSMutableArray new]; + for (NSString *line in lines) { + [newLines addObject:[NSString stringWithFormat:@" %@", line]]; + } + return newLines; +} diff --git a/Source/Internal/IGListSectionMap+DebugDescription.h b/Source/Internal/IGListSectionMap+DebugDescription.h new file mode 100644 index 00000000..299b8fdc --- /dev/null +++ b/Source/Internal/IGListSectionMap+DebugDescription.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "IGListSectionMap.h" + +@interface IGListSectionMap (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/Source/Internal/IGListSectionMap+DebugDescription.m b/Source/Internal/IGListSectionMap+DebugDescription.m new file mode 100644 index 00000000..54326d8c --- /dev/null +++ b/Source/Internal/IGListSectionMap+DebugDescription.m @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "IGListSectionMap+DebugDescription.h" + +@implementation IGListSectionMap (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [self enumerateUsingBlock:^(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop) { + [debug addObject:[NSString stringWithFormat:@"Object and section controller at section: %zi:", section]]; + [debug addObject:[NSString stringWithFormat:@" %@", object]]; + [debug addObject:[NSString stringWithFormat:@" %@", sectionController]]; + }]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/Source/Internal/UICollectionView+DebugDescription.h b/Source/Internal/UICollectionView+DebugDescription.h new file mode 100644 index 00000000..d9b016de --- /dev/null +++ b/Source/Internal/UICollectionView+DebugDescription.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface UICollectionView (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/Source/Internal/UICollectionView+DebugDescription.m b/Source/Internal/UICollectionView+DebugDescription.m new file mode 100644 index 00000000..26dde27d --- /dev/null +++ b/Source/Internal/UICollectionView+DebugDescription.m @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "UICollectionView+DebugDescription.h" + +@implementation UICollectionView (DebugDescription) + +- (NSArray *)debugDescriptionLines; { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Class: %@, instance: %p", NSStringFromClass(self.class), self]]; + [debug addObject:[NSString stringWithFormat:@"Data source: %@", self.dataSource]]; + [debug addObject:[NSString stringWithFormat:@"Delegate: %@", self.delegate]]; + [debug addObject:[NSString stringWithFormat:@"Layout: %@", self.collectionViewLayout]]; + [debug addObject:[NSString stringWithFormat:@"Frame: %@, bounds: %@", + NSStringFromCGRect(self.frame), NSStringFromCGRect(self.bounds)]]; + + const NSInteger sections = [self numberOfSections]; + [debug addObject:[NSString stringWithFormat:@"Number of sections: %zi", sections]]; + + for (NSInteger section = 0; section < sections; section++) { + [debug addObject:[NSString stringWithFormat:@" %zi items in section %zi", + [self numberOfItemsInSection:section], section]]; + } + + [debug addObject:@"Visible cell details:"]; + NSArray *visibleIndexPaths = [[self indexPathsForVisibleItems] sortedArrayUsingSelector:@selector(compare:)]; + for (NSIndexPath *path in visibleIndexPaths) { + [debug addObject:[NSString stringWithFormat:@" Visible cell at section %zi, item %zi:", + path.section, path.item]]; + [debug addObject:[NSString stringWithFormat:@" %@", [[self cellForItemAtIndexPath:path] description] ?: @""]]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/Tests/IGListDebuggerTests.m b/Tests/IGListDebuggerTests.m new file mode 100644 index 00000000..695f0045 --- /dev/null +++ b/Tests/IGListDebuggerTests.m @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import + +#import "IGListDebugger.h" +#import "IGListAdapterUpdaterInternal.h" +#import "IGListTestAdapterDataSource.h" +#import "IGListMoveIndexInternal.h" +#import "IGListMoveIndexPathInternal.h" + +@interface IGListDebuggerTests : XCTestCase + +@end + +@implementation IGListDebuggerTests + +- (void)test_whenSearchingAdapterInstances_thatCorrectCountReturned { + UIViewController *controller = [UIViewController new]; + UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[UICollectionViewFlowLayout new]]; + IGListAdapterUpdater *updater = [IGListAdapterUpdater new]; + NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:0]; + updater.applyingUpdateData = [[IGListBatchUpdateData alloc] initWithInsertSections:[NSIndexSet indexSetWithIndex:1] + deleteSections:[NSIndexSet indexSetWithIndex:2] + moveSections:[NSSet setWithObject:[[IGListMoveIndex alloc] initWithFrom:3 to:4]] + insertIndexPaths:@[path] + deleteIndexPaths:@[path] + moveIndexPaths:@[[[IGListMoveIndexPath alloc] initWithFrom:path to:path]]]; + IGListTestAdapterDataSource *dataSource = [IGListTestAdapterDataSource new]; + dataSource.objects = @[@1, @2, @3]; + IGListAdapter *adapter1 = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:nil workingRangeSize:0]; + adapter1.collectionView = collectionView; + adapter1.dataSource = dataSource; + IGListAdapter *adapter2 = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:controller workingRangeSize:2]; + adapter2.collectionView = collectionView; + IGListAdapter *adapter3 = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:controller workingRangeSize:2]; + adapter3.collectionView = collectionView; + + NSArray *descriptions = [IGListDebugger adapterDescriptions]; + XCTAssertEqual(descriptions.count, 3); +} + +@end