mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
IGListKit Support II: Electric Boogaloo (#2942)
* Reimplement IGListKit support in a cleaner way * Rename and fix some stuff * Fix supplementaries more * Update docs * Update test * Cleanup minor things * Tweak it * Indentation * Remove irrelevant changes * Break out cell into its own file * Fix indentation * Address feedback
This commit is contained in:
@@ -17,6 +17,7 @@ before_install:
|
|||||||
install: echo "<3"
|
install: echo "<3"
|
||||||
env:
|
env:
|
||||||
- MODE=tests
|
- MODE=tests
|
||||||
|
- MODE=tests_listkit
|
||||||
- MODE=examples-pt1
|
- MODE=examples-pt1
|
||||||
- MODE=examples-pt2
|
- MODE=examples-pt2
|
||||||
- MODE=examples-pt3
|
- MODE=examples-pt3
|
||||||
|
|||||||
394
ASDKListKit/ASDKListKit.xcodeproj/project.pbxproj
Normal file
394
ASDKListKit/ASDKListKit.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 46;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
BD860CAB842324FDF0B3105C /* libPods-ASDKListKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FEACA22D54B3609C19BB4CE /* libPods-ASDKListKitTests.a */; };
|
||||||
|
CC5532391E16F2A90011C01F /* ASListTestSupplementarySource.m in Sources */ = {isa = PBXBuildFile; fileRef = CC55322D1E16F2A90011C01F /* ASListTestSupplementarySource.m */; };
|
||||||
|
CC55323A1E16F2A90011C01F /* ASListTestSupplementaryNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC55322F1E16F2A90011C01F /* ASListTestSupplementaryNode.m */; };
|
||||||
|
CC55323B1E16F2A90011C01F /* ASListKitTestAdapterDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532311E16F2A90011C01F /* ASListKitTestAdapterDataSource.m */; };
|
||||||
|
CC55323C1E16F2A90011C01F /* ASListTestSection.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532331E16F2A90011C01F /* ASListTestSection.m */; };
|
||||||
|
CC55323D1E16F2A90011C01F /* ASListTestCellNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532351E16F2A90011C01F /* ASListTestCellNode.m */; };
|
||||||
|
CC55323E1E16F2A90011C01F /* ASListTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532371E16F2A90011C01F /* ASListTestObject.m */; };
|
||||||
|
CC55323F1E16F2A90011C01F /* ASListKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532381E16F2A90011C01F /* ASListKitTests.m */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
1FEACA22D54B3609C19BB4CE /* libPods-ASDKListKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ASDKListKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
B1FDA57F88BB590E403D7BB8 /* Pods-ASDKListKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASDKListKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ASDKListKitTests/Pods-ASDKListKitTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
CC5532231E16EB9D0011C01F /* ASDKListKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ASDKListKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
CC5532281E16EB9D0011C01F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
CC55322C1E16F2A90011C01F /* ASListTestSupplementarySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListTestSupplementarySource.h; sourceTree = "<group>"; };
|
||||||
|
CC55322D1E16F2A90011C01F /* ASListTestSupplementarySource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListTestSupplementarySource.m; sourceTree = "<group>"; };
|
||||||
|
CC55322E1E16F2A90011C01F /* ASListTestSupplementaryNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListTestSupplementaryNode.h; sourceTree = "<group>"; };
|
||||||
|
CC55322F1E16F2A90011C01F /* ASListTestSupplementaryNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListTestSupplementaryNode.m; sourceTree = "<group>"; };
|
||||||
|
CC5532301E16F2A90011C01F /* ASListKitTestAdapterDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListKitTestAdapterDataSource.h; sourceTree = "<group>"; };
|
||||||
|
CC5532311E16F2A90011C01F /* ASListKitTestAdapterDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListKitTestAdapterDataSource.m; sourceTree = "<group>"; };
|
||||||
|
CC5532321E16F2A90011C01F /* ASListTestSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListTestSection.h; sourceTree = "<group>"; };
|
||||||
|
CC5532331E16F2A90011C01F /* ASListTestSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListTestSection.m; sourceTree = "<group>"; };
|
||||||
|
CC5532341E16F2A90011C01F /* ASListTestCellNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListTestCellNode.h; sourceTree = "<group>"; };
|
||||||
|
CC5532351E16F2A90011C01F /* ASListTestCellNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListTestCellNode.m; sourceTree = "<group>"; };
|
||||||
|
CC5532361E16F2A90011C01F /* ASListTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASListTestObject.h; sourceTree = "<group>"; };
|
||||||
|
CC5532371E16F2A90011C01F /* ASListTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListTestObject.m; sourceTree = "<group>"; };
|
||||||
|
CC5532381E16F2A90011C01F /* ASListKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASListKitTests.m; sourceTree = "<group>"; };
|
||||||
|
CC55326C1E16F67A0011C01F /* ASXCTExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASXCTExtensions.h; sourceTree = "<group>"; };
|
||||||
|
D6BDED6F23A72F40F571EEF0 /* Pods-ASDKListKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASDKListKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ASDKListKitTests/Pods-ASDKListKitTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
CC5532201E16EB9D0011C01F /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
BD860CAB842324FDF0B3105C /* libPods-ASDKListKitTests.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
72C6817154F7AC11E373624A /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
B1FDA57F88BB590E403D7BB8 /* Pods-ASDKListKitTests.debug.xcconfig */,
|
||||||
|
D6BDED6F23A72F40F571EEF0 /* Pods-ASDKListKitTests.release.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
74DAA5F5D522433F103348B7 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1FEACA22D54B3609C19BB4CE /* libPods-ASDKListKitTests.a */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CC5532181E16EB7A0011C01F = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC5532251E16EB9D0011C01F /* ASDKListKitTests */,
|
||||||
|
CC5532241E16EB9D0011C01F /* Products */,
|
||||||
|
72C6817154F7AC11E373624A /* Pods */,
|
||||||
|
74DAA5F5D522433F103348B7 /* Frameworks */,
|
||||||
|
);
|
||||||
|
indentWidth = 2;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 2;
|
||||||
|
usesTabs = 0;
|
||||||
|
};
|
||||||
|
CC5532241E16EB9D0011C01F /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC5532231E16EB9D0011C01F /* ASDKListKitTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CC5532251E16EB9D0011C01F /* ASDKListKitTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC55326D1E16F67D0011C01F /* Common */,
|
||||||
|
CC55326E1E170A740011C01F /* ListKit Fixtures */,
|
||||||
|
CC5532381E16F2A90011C01F /* ASListKitTests.m */,
|
||||||
|
CC5532281E16EB9D0011C01F /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = ASDKListKitTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CC55326D1E16F67D0011C01F /* Common */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC55326C1E16F67A0011C01F /* ASXCTExtensions.h */,
|
||||||
|
);
|
||||||
|
name = Common;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CC55326E1E170A740011C01F /* ListKit Fixtures */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC55322C1E16F2A90011C01F /* ASListTestSupplementarySource.h */,
|
||||||
|
CC55322D1E16F2A90011C01F /* ASListTestSupplementarySource.m */,
|
||||||
|
CC55322E1E16F2A90011C01F /* ASListTestSupplementaryNode.h */,
|
||||||
|
CC55322F1E16F2A90011C01F /* ASListTestSupplementaryNode.m */,
|
||||||
|
CC5532301E16F2A90011C01F /* ASListKitTestAdapterDataSource.h */,
|
||||||
|
CC5532311E16F2A90011C01F /* ASListKitTestAdapterDataSource.m */,
|
||||||
|
CC5532321E16F2A90011C01F /* ASListTestSection.h */,
|
||||||
|
CC5532331E16F2A90011C01F /* ASListTestSection.m */,
|
||||||
|
CC5532341E16F2A90011C01F /* ASListTestCellNode.h */,
|
||||||
|
CC5532351E16F2A90011C01F /* ASListTestCellNode.m */,
|
||||||
|
CC5532361E16F2A90011C01F /* ASListTestObject.h */,
|
||||||
|
CC5532371E16F2A90011C01F /* ASListTestObject.m */,
|
||||||
|
);
|
||||||
|
name = "ListKit Fixtures";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
CC5532221E16EB9D0011C01F /* ASDKListKitTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = CC5532291E16EB9D0011C01F /* Build configuration list for PBXNativeTarget "ASDKListKitTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
614B24BFF3DA58512D2E2147 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
CC55321F1E16EB9D0011C01F /* Sources */,
|
||||||
|
CC5532201E16EB9D0011C01F /* Frameworks */,
|
||||||
|
CC5532211E16EB9D0011C01F /* Resources */,
|
||||||
|
989E6C194A1983B8B21AB82F /* [CP] Embed Pods Frameworks */,
|
||||||
|
876CE14CAF6A87E34577E157 /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = ASDKListKitTests;
|
||||||
|
productName = ASDKListKitTests;
|
||||||
|
productReference = CC5532231E16EB9D0011C01F /* ASDKListKitTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
CC5532191E16EB7A0011C01F /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 0820;
|
||||||
|
TargetAttributes = {
|
||||||
|
CC5532221E16EB9D0011C01F = {
|
||||||
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = CC55321C1E16EB7A0011C01F /* Build configuration list for PBXProject "ASDKListKit" */;
|
||||||
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
developmentRegion = English;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = CC5532181E16EB7A0011C01F;
|
||||||
|
productRefGroup = CC5532241E16EB9D0011C01F /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
CC5532221E16EB9D0011C01F /* ASDKListKitTests */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
CC5532211E16EB9D0011C01F /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
614B24BFF3DA58512D2E2147 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
876CE14CAF6A87E34577E157 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ASDKListKitTests/Pods-ASDKListKitTests-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
989E6C194A1983B8B21AB82F /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ASDKListKitTests/Pods-ASDKListKitTests-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
CC55321F1E16EB9D0011C01F /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
CC55323E1E16F2A90011C01F /* ASListTestObject.m in Sources */,
|
||||||
|
CC5532391E16F2A90011C01F /* ASListTestSupplementarySource.m in Sources */,
|
||||||
|
CC55323D1E16F2A90011C01F /* ASListTestCellNode.m in Sources */,
|
||||||
|
CC55323B1E16F2A90011C01F /* ASListKitTestAdapterDataSource.m in Sources */,
|
||||||
|
CC55323C1E16F2A90011C01F /* ASListTestSection.m in Sources */,
|
||||||
|
CC55323F1E16F2A90011C01F /* ASListKitTests.m in Sources */,
|
||||||
|
CC55323A1E16F2A90011C01F /* ASListTestSupplementaryNode.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
CC55321D1E16EB7A0011C01F /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
CC55321E1E16EB7A0011C01F /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
CC55322A1E16EB9D0011C01F /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = B1FDA57F88BB590E403D7BB8 /* Pods-ASDKListKitTests.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
INFOPLIST_FILE = ASDKListKitTests/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = asyncdisplaykit.ASDKListKitTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
CC55322B1E16EB9D0011C01F /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D6BDED6F23A72F40F571EEF0 /* Pods-ASDKListKitTests.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
INFOPLIST_FILE = ASDKListKitTests/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = asyncdisplaykit.ASDKListKitTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
CC55321C1E16EB7A0011C01F /* Build configuration list for PBXProject "ASDKListKit" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
CC55321D1E16EB7A0011C01F /* Debug */,
|
||||||
|
CC55321E1E16EB7A0011C01F /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
CC5532291E16EB9D0011C01F /* Build configuration list for PBXNativeTarget "ASDKListKitTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
CC55322A1E16EB9D0011C01F /* Debug */,
|
||||||
|
CC55322B1E16EB9D0011C01F /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = CC5532191E16EB7A0011C01F /* Project object */;
|
||||||
|
}
|
||||||
7
ASDKListKit/ASDKListKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ASDKListKit/ASDKListKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:ASDKListKit.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
10
ASDKListKit/ASDKListKit.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
ASDKListKit/ASDKListKit.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:ASDKListKit.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// ASListKitTestAdapterDataSource.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
|
@interface ASListKitTestAdapterDataSource : NSObject <IGListAdapterDataSource>
|
||||||
|
|
||||||
|
// array of numbers which is then passed to -[IGListTestSection setItems:]
|
||||||
|
@property (nonatomic, strong) NSArray <NSNumber *> *objects;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// ASListKitTestAdapterDataSource.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListKitTestAdapterDataSource.h"
|
||||||
|
#import "ASListTestSection.h"
|
||||||
|
|
||||||
|
@implementation ASListKitTestAdapterDataSource
|
||||||
|
|
||||||
|
- (NSArray *)objectsForListAdapter:(IGListAdapter *)listAdapter
|
||||||
|
{
|
||||||
|
return self.objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IGListSectionController <IGListSectionType> *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object
|
||||||
|
{
|
||||||
|
ASListTestSection *section = [[ASListTestSection alloc] init];
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable UIView *)emptyViewForListAdapter:(IGListAdapter *)listAdapter
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
110
ASDKListKit/ASDKListKitTests/ASListKitTests.m
Normal file
110
ASDKListKit/ASDKListKitTests/ASListKitTests.m
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// ASListKitTests.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
#import "ASListKitTestAdapterDataSource.h"
|
||||||
|
#import "ASXCTExtensions.h"
|
||||||
|
#import <JGMethodSwizzler/JGMethodSwizzler.h>
|
||||||
|
|
||||||
|
@interface ASListKitTests : XCTestCase
|
||||||
|
|
||||||
|
@property (nonatomic, strong) ASCollectionNode *collectionNode;
|
||||||
|
@property (nonatomic, strong) UICollectionView *collectionView;
|
||||||
|
@property (nonatomic, strong) IGListAdapter *adapter;
|
||||||
|
@property (nonatomic, strong) ASListKitTestAdapterDataSource *dataSource;
|
||||||
|
@property (nonatomic, strong) UICollectionViewFlowLayout *layout;
|
||||||
|
@property (nonatomic, strong) UIWindow *window;
|
||||||
|
@property (nonatomic) NSInteger reloadDataCount;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASListKitTests
|
||||||
|
|
||||||
|
- (void)setUp
|
||||||
|
{
|
||||||
|
[super setUp];
|
||||||
|
|
||||||
|
[ASCollectionView swizzleInstanceMethod:@selector(reloadData) withReplacement:JGMethodReplacementProviderBlock {
|
||||||
|
return JGMethodReplacement(void, ASCollectionView *) {
|
||||||
|
JGOriginalImplementation(void);
|
||||||
|
_reloadDataCount++;
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
|
||||||
|
self.layout = [[UICollectionViewFlowLayout alloc] init];
|
||||||
|
self.collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:self.layout];
|
||||||
|
self.collectionNode.frame = self.window.bounds;
|
||||||
|
self.collectionView = self.collectionNode.view;
|
||||||
|
|
||||||
|
[self.window addSubnode:self.collectionNode];
|
||||||
|
|
||||||
|
IGListAdapterUpdater *updater = [[IGListAdapterUpdater alloc] init];
|
||||||
|
|
||||||
|
self.dataSource = [[ASListKitTestAdapterDataSource alloc] init];
|
||||||
|
self.adapter = [[IGListAdapter alloc] initWithUpdater:updater
|
||||||
|
viewController:nil
|
||||||
|
workingRangeSize:0];
|
||||||
|
self.adapter.dataSource = self.dataSource;
|
||||||
|
[self.adapter setASDKCollectionNode:self.collectionNode];
|
||||||
|
XCTAssertNotNil(self.adapter.collectionView, @"Adapter was not bound to collection view. You may have a stale copy of AsyncDisplayKit that was built without IG_LIST_KIT. Clean Builder Folder IMO.");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tearDown
|
||||||
|
{
|
||||||
|
[super tearDown];
|
||||||
|
XCTAssert([ASCollectionView deswizzleAllMethods]);
|
||||||
|
self.reloadDataCount = 0;
|
||||||
|
self.window = nil;
|
||||||
|
self.collectionNode = nil;
|
||||||
|
self.collectionView = nil;
|
||||||
|
self.adapter = nil;
|
||||||
|
self.dataSource = nil;
|
||||||
|
self.layout = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test_whenAdapterUpdated_withObjectsOverflow_thatVisibleObjectsIsSubsetOfAllObjects
|
||||||
|
{
|
||||||
|
// each section controller returns n items sized 100x10
|
||||||
|
self.dataSource.objects = @[@1, @2, @3, @4, @5, @6];
|
||||||
|
XCTestExpectation *e = [self expectationWithDescription:@"Data update completed"];
|
||||||
|
|
||||||
|
[self.adapter performUpdatesAnimated:NO completion:^(BOOL finished) {
|
||||||
|
[e fulfill];
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||||
|
self.collectionNode.view.contentOffset = CGPointMake(0, 30);
|
||||||
|
[self.collectionNode.view layoutIfNeeded];
|
||||||
|
|
||||||
|
|
||||||
|
NSArray *visibleObjects = [[self.adapter visibleObjects] sortedArrayUsingSelector:@selector(compare:)];
|
||||||
|
NSArray *expectedObjects = @[@3, @4, @5];
|
||||||
|
XCTAssertEqualObjects(visibleObjects, expectedObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test_whenCollectionViewIsNotInAWindow_updaterDoesNotJustCallReloadData
|
||||||
|
{
|
||||||
|
[self.collectionView removeFromSuperview];
|
||||||
|
|
||||||
|
[self.collectionView layoutIfNeeded];
|
||||||
|
self.dataSource.objects = @[@1, @2, @3, @4, @5, @6];
|
||||||
|
XCTestExpectation *e = [self expectationWithDescription:@"Data update completed"];
|
||||||
|
|
||||||
|
[self.adapter performUpdatesAnimated:NO completion:^(BOOL finished) {
|
||||||
|
[e fulfill];
|
||||||
|
}];
|
||||||
|
[self waitForExpectationsWithTimeout:1 handler:nil];
|
||||||
|
[self.collectionView layoutIfNeeded];
|
||||||
|
|
||||||
|
XCTAssertEqual(self.reloadDataCount, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
13
ASDKListKit/ASDKListKitTests/ASListTestCellNode.h
Normal file
13
ASDKListKit/ASDKListKitTests/ASListTestCellNode.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ASListTestCellNode.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface ASListTestCellNode : ASCellNode
|
||||||
|
|
||||||
|
@end
|
||||||
13
ASDKListKit/ASDKListKitTests/ASListTestCellNode.m
Normal file
13
ASDKListKit/ASDKListKitTests/ASListTestCellNode.m
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ASListTestCellNode.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListTestCellNode.h"
|
||||||
|
|
||||||
|
@implementation ASListTestCellNode
|
||||||
|
|
||||||
|
@end
|
||||||
22
ASDKListKit/ASDKListKitTests/ASListTestObject.h
Normal file
22
ASDKListKit/ASDKListKitTests/ASListTestObject.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// ASListTestObject.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface ASListTestObject : NSObject <IGListDiffable, NSCopying>
|
||||||
|
|
||||||
|
- (instancetype)initWithKey:(id <NSCopying>)key value:(id)value;
|
||||||
|
|
||||||
|
@property (nonatomic, strong, readonly) id key;
|
||||||
|
@property (nonatomic, strong) id value;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
49
ASDKListKit/ASDKListKitTests/ASListTestObject.m
Normal file
49
ASDKListKit/ASDKListKitTests/ASListTestObject.m
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// ASListTestObject.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListTestObject.h"
|
||||||
|
|
||||||
|
@implementation ASListTestObject
|
||||||
|
|
||||||
|
- (instancetype)initWithKey:(id)key value:(id)value
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_key = [key copy];
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)copyWithZone:(NSZone *)zone
|
||||||
|
{
|
||||||
|
return [[ASListTestObject alloc] initWithKey:self.key value:self.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - IGListDiffable
|
||||||
|
|
||||||
|
- (id<NSObject>)diffIdentifier
|
||||||
|
{
|
||||||
|
return self.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToDiffableObject:(id)object
|
||||||
|
{
|
||||||
|
if (object == self) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
if ([object isKindOfClass:[ASListTestObject class]]) {
|
||||||
|
id k1 = self.key;
|
||||||
|
id k2 = [object key];
|
||||||
|
id v1 = self.value;
|
||||||
|
id v2 = [(ASListTestObject *)object value];
|
||||||
|
return (v1 == v2 || [v1 isEqual:v2]) && (k1 == k2 || [k1 isEqual:k2]);
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
18
ASDKListKit/ASDKListKitTests/ASListTestSection.h
Normal file
18
ASDKListKit/ASDKListKitTests/ASListTestSection.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSection.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface ASListTestSection : IGListSectionController <IGListSectionType, ASSectionController>
|
||||||
|
|
||||||
|
@property (nonatomic) NSInteger itemCount;
|
||||||
|
|
||||||
|
@property (nonatomic) NSInteger selectedItemIndex;
|
||||||
|
|
||||||
|
@end
|
||||||
58
ASDKListKit/ASDKListKitTests/ASListTestSection.m
Normal file
58
ASDKListKit/ASDKListKitTests/ASListTestSection.m
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSection.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListTestSection.h"
|
||||||
|
#import "ASListTestCellNode.h"
|
||||||
|
|
||||||
|
@implementation ASListTestSection
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init])
|
||||||
|
{
|
||||||
|
_selectedItemIndex = NSNotFound;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)numberOfItems
|
||||||
|
{
|
||||||
|
return self.itemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeForItemAtIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
ASDisplayNodeFailAssert(@"Did not expect %@ to be called.", NSStringFromSelector(_cmd));
|
||||||
|
return CGSizeMake(100, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASIGSectionControllerCellForIndexImplementation
|
||||||
|
|
||||||
|
- (void)didUpdateToObject:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSNumber class]])
|
||||||
|
{
|
||||||
|
self.itemCount = [object integerValue];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didSelectItemAtIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
self.selectedItemIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASCellNodeBlock)nodeBlockForItemAtIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
return ^{
|
||||||
|
ASListTestCellNode *node = [[ASListTestCellNode alloc] init];
|
||||||
|
node.style.preferredSize = CGSizeMake(100, 10);
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
13
ASDKListKit/ASDKListKitTests/ASListTestSupplementaryNode.h
Normal file
13
ASDKListKit/ASDKListKitTests/ASListTestSupplementaryNode.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSupplementaryNode.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface ASListTestSupplementaryNode : ASCellNode
|
||||||
|
|
||||||
|
@end
|
||||||
13
ASDKListKit/ASDKListKitTests/ASListTestSupplementaryNode.m
Normal file
13
ASDKListKit/ASDKListKitTests/ASListTestSupplementaryNode.m
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSupplementaryNode.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListTestSupplementaryNode.h"
|
||||||
|
|
||||||
|
@implementation ASListTestSupplementaryNode
|
||||||
|
|
||||||
|
@end
|
||||||
20
ASDKListKit/ASDKListKitTests/ASListTestSupplementarySource.h
Normal file
20
ASDKListKit/ASDKListKitTests/ASListTestSupplementarySource.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSupplementarySource.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface ASListTestSupplementarySource : NSObject <IGListSupplementaryViewSource, ASSupplementaryNodeSource>
|
||||||
|
|
||||||
|
@property (nonatomic, strong, readwrite) NSArray<NSString *> *supportedElementKinds;
|
||||||
|
|
||||||
|
@property (nonatomic, weak) id<IGListCollectionContext> collectionContext;
|
||||||
|
|
||||||
|
@property (nonatomic, weak) IGListSectionController<IGListSectionType> *sectionController;
|
||||||
|
|
||||||
|
@end
|
||||||
24
ASDKListKit/ASDKListKitTests/ASListTestSupplementarySource.m
Normal file
24
ASDKListKit/ASDKListKitTests/ASListTestSupplementarySource.m
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// ASListTestSupplementarySource.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/25/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASListTestSupplementarySource.h"
|
||||||
|
#import "ASListTestSupplementaryNode.h"
|
||||||
|
|
||||||
|
@implementation ASListTestSupplementarySource
|
||||||
|
|
||||||
|
ASIGSupplementarySourceViewForSupplementaryElementImplementation(self.sectionController)
|
||||||
|
ASIGSupplementarySourceSizeForSupplementaryElementImplementation
|
||||||
|
|
||||||
|
- (ASCellNode *)nodeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
ASListTestSupplementaryNode *node = [[ASListTestSupplementaryNode alloc] init];
|
||||||
|
node.style.preferredSize = CGSizeMake(100, 10);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
36
ASDKListKit/ASDKListKitTests/ASXCTExtensions.h
Normal file
36
ASDKListKit/ASDKListKitTests/ASXCTExtensions.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* XCTest extensions for CGGeometry.
|
||||||
|
*
|
||||||
|
* Prefer these to XCTAssert(CGRectEqualToRect(...)) because you get output
|
||||||
|
* that tells you what went wrong.
|
||||||
|
* Could use NSValue, but using strings makes the description messages shorter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <XCTest/XCTestAssertionsImpl.h>
|
||||||
|
|
||||||
|
#define ASXCTAssertEqualSizes(s0, s1, ...) \
|
||||||
|
_XCTPrimitiveAssertEqualObjects(self, NSStringFromCGSize(s0), @#s0, NSStringFromCGSize(s1), @#s1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertNotEqualSizes(s0, s1, ...) \
|
||||||
|
_XCTPrimitiveAssertNotEqualObjects(self, NSStringFromCGSize(s0), @#s0, NSStringFromCGSize(s1), @#s1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertEqualPoints(p0, p1, ...) \
|
||||||
|
_XCTPrimitiveAssertEqualObjects(self, NSStringFromCGPoint(p0), @#p0, NSStringFromCGPoint(p1), @#p1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertNotEqualPoints(p0, p1, ...) \
|
||||||
|
_XCTPrimitiveAssertNotEqualObjects(self, NSStringFromCGPoint(p0), @#p0, NSStringFromCGPoint(p1), @#p1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertEqualRects(r0, r1, ...) \
|
||||||
|
_XCTPrimitiveAssertEqualObjects(self, NSStringFromCGRect(r0), @#r0, NSStringFromCGRect(r1), @#r1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertNotEqualRects(r0, r1, ...) \
|
||||||
|
_XCTPrimitiveAssertNotEqualObjects(self, NSStringFromCGRect(r0), @#r0, NSStringFromCGRect(r1), @#r1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertEqualDimensions(r0, r1, ...) \
|
||||||
|
_XCTPrimitiveAssertEqualObjects(self, NSStringFromASDimension(r0), @#r0, NSStringFromASDimension(r1), @#r1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertNotEqualDimensions(r0, r1, ...) \
|
||||||
|
_XCTPrimitiveAssertNotEqualObjects(self, NSStringFromASDimension(r0), @#r0, NSStringFromASDimension(r1), @#r1, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASXCTAssertEqualSizeRanges(r0, r1, ...) \
|
||||||
|
_XCTPrimitiveAssertEqualObjects(self, NSStringFromASSizeRange(r0), @#r0, NSStringFromASSizeRange(r1), @#r1, __VA_ARGS__)
|
||||||
22
ASDKListKit/ASDKListKitTests/Info.plist
Normal file
22
ASDKListKit/ASDKListKitTests/Info.plist
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
ASDKListKit/Podfile
Normal file
8
ASDKListKit/Podfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
source 'https://github.com/CocoaPods/Specs.git'
|
||||||
|
|
||||||
|
platform :ios, '8.0'
|
||||||
|
target 'ASDKListKitTests' do
|
||||||
|
pod 'AsyncDisplayKit/IGListKit', :path => '..'
|
||||||
|
pod 'JGMethodSwizzler', :git => 'https://github.com/JonasGessner/JGMethodSwizzler', :branch => 'master'
|
||||||
|
end
|
||||||
|
|
||||||
@@ -47,6 +47,12 @@ Pod::Spec.new do |spec|
|
|||||||
pin.dependency 'PINRemoteImage/PINCache'
|
pin.dependency 'PINRemoteImage/PINCache'
|
||||||
pin.dependency 'AsyncDisplayKit/Core'
|
pin.dependency 'AsyncDisplayKit/Core'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
spec.subspec 'IGListKit' do |igl|
|
||||||
|
igl.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) IG_LIST_KIT=1' }
|
||||||
|
igl.dependency 'IGListKit', '2.1.0'
|
||||||
|
igl.dependency 'AsyncDisplayKit/Core'
|
||||||
|
end
|
||||||
|
|
||||||
# Include optional PINRemoteImage module
|
# Include optional PINRemoteImage module
|
||||||
spec.default_subspec = 'PINRemoteImage'
|
spec.default_subspec = 'PINRemoteImage'
|
||||||
|
|||||||
@@ -459,15 +459,30 @@
|
|||||||
CC4C2A7A1D8902350039ACAB /* ASTraceEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CC4C2A751D88E3BF0039ACAB /* ASTraceEvent.h */; };
|
CC4C2A7A1D8902350039ACAB /* ASTraceEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CC4C2A751D88E3BF0039ACAB /* ASTraceEvent.h */; };
|
||||||
CC54A81C1D70079800296A24 /* ASDispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = CC54A81B1D70077A00296A24 /* ASDispatch.h */; };
|
CC54A81C1D70079800296A24 /* ASDispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = CC54A81B1D70077A00296A24 /* ASDispatch.h */; };
|
||||||
CC54A81E1D7008B300296A24 /* ASDispatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC54A81D1D7008B300296A24 /* ASDispatchTests.m */; };
|
CC54A81E1D7008B300296A24 /* ASDispatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC54A81D1D7008B300296A24 /* ASDispatchTests.m */; };
|
||||||
|
CC6363E21E32C00800D8A8DE /* ASCollectionInteropProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6363E11E32C00800D8A8DE /* ASCollectionInteropProtocols.h */; };
|
||||||
|
CC6363E31E32C01900D8A8DE /* ASCollectionInteropProtocols.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CC6363E11E32C00800D8A8DE /* ASCollectionInteropProtocols.h */; };
|
||||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; };
|
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; };
|
||||||
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
|
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
|
||||||
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
CC8525151E3FC253008EABE6 /* _ASCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = CC8525131E3FC253008EABE6 /* _ASCollectionViewCell.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||||
|
CC8525161E3FC253008EABE6 /* _ASCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8525141E3FC253008EABE6 /* _ASCollectionViewCell.m */; };
|
||||||
|
CC8525171E3FC253008EABE6 /* _ASCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8525141E3FC253008EABE6 /* _ASCollectionViewCell.m */; };
|
||||||
|
CC8525181E3FC316008EABE6 /* _ASCollectionViewCell.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CC8525131E3FC253008EABE6 /* _ASCollectionViewCell.h */; };
|
||||||
CC87BB951DA8193C0090E380 /* ASCellNode+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */; };
|
CC87BB951DA8193C0090E380 /* ASCellNode+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */; };
|
||||||
CC8B05D61D73836400F54286 /* ASPerformanceTestContext.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */; };
|
CC8B05D61D73836400F54286 /* ASPerformanceTestContext.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */; };
|
||||||
CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */; };
|
CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */; };
|
||||||
CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */; };
|
CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */; };
|
||||||
CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */; };
|
CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */; };
|
||||||
|
CCE04B1F1E313EA7006AEBBB /* ASSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
CCE04B221E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */; };
|
||||||
|
CCE04B231E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m in Sources */ = {isa = PBXBuildFile; fileRef = CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */; };
|
||||||
|
CCE04B241E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m in Sources */ = {isa = PBXBuildFile; fileRef = CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */; };
|
||||||
|
CCE04B2C1E314A32006AEBBB /* ASSupplementaryNodeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
CCE04B2E1E314A9C006AEBBB /* ASSectionController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */; };
|
||||||
|
CCE04B2F1E314A9C006AEBBB /* ASSupplementaryNodeSource.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */; };
|
||||||
|
CCE04B301E314A9C006AEBBB /* IGListAdapter+AsyncDisplayKit.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */; };
|
||||||
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; };
|
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; };
|
||||||
|
CCF92DCD1E3155180019E9C6 /* ASIGListKitMethodImplementations.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF92DCC1E3155180019E9C6 /* ASIGListKitMethodImplementations.h */; };
|
||||||
D785F6631A74327E00291744 /* ASScrollNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.mm */; };
|
D785F6631A74327E00291744 /* ASScrollNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.mm */; };
|
||||||
DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */; };
|
DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */; };
|
||||||
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
@@ -674,6 +689,7 @@
|
|||||||
dstPath = "include/$(PRODUCT_NAME)";
|
dstPath = "include/$(PRODUCT_NAME)";
|
||||||
dstSubfolderSpec = 16;
|
dstSubfolderSpec = 16;
|
||||||
files = (
|
files = (
|
||||||
|
CC8525181E3FC316008EABE6 /* _ASCollectionViewCell.h in CopyFiles */,
|
||||||
690ED59D1E36D140000627C0 /* ASImageNode+tvOS.h in CopyFiles */,
|
690ED59D1E36D140000627C0 /* ASImageNode+tvOS.h in CopyFiles */,
|
||||||
690ED59C1E36D13A000627C0 /* ASControlNode+tvOS.h in CopyFiles */,
|
690ED59C1E36D13A000627C0 /* ASControlNode+tvOS.h in CopyFiles */,
|
||||||
690ED58F1E36BCBF000627C0 /* ASLayoutElementStylePrivate.h in CopyFiles */,
|
690ED58F1E36BCBF000627C0 /* ASLayoutElementStylePrivate.h in CopyFiles */,
|
||||||
@@ -682,6 +698,10 @@
|
|||||||
692BE8D81E36B66500C86D87 /* ASLayoutSpecPrivate.h in CopyFiles */,
|
692BE8D81E36B66500C86D87 /* ASLayoutSpecPrivate.h in CopyFiles */,
|
||||||
6947B0C71E36B5B60007C478 /* ASStackPositionedLayout.h in CopyFiles */,
|
6947B0C71E36B5B60007C478 /* ASStackPositionedLayout.h in CopyFiles */,
|
||||||
6947B0C61E36B5A90007C478 /* ASStackUnpositionedLayout.h in CopyFiles */,
|
6947B0C61E36B5A90007C478 /* ASStackUnpositionedLayout.h in CopyFiles */,
|
||||||
|
CC6363E31E32C01900D8A8DE /* ASCollectionInteropProtocols.h in CopyFiles */,
|
||||||
|
CCE04B2E1E314A9C006AEBBB /* ASSectionController.h in CopyFiles */,
|
||||||
|
CCE04B2F1E314A9C006AEBBB /* ASSupplementaryNodeSource.h in CopyFiles */,
|
||||||
|
CCE04B301E314A9C006AEBBB /* IGListAdapter+AsyncDisplayKit.h in CopyFiles */,
|
||||||
693DA5141E25373100F66DF4 /* ASDimensionDeprecated.h in CopyFiles */,
|
693DA5141E25373100F66DF4 /* ASDimensionDeprecated.h in CopyFiles */,
|
||||||
693DA50F1E2536A600F66DF4 /* ASDimensionInternal.h in CopyFiles */,
|
693DA50F1E2536A600F66DF4 /* ASDimensionInternal.h in CopyFiles */,
|
||||||
68C2155C1DE11AA80019C4BC /* ASObjectDescriptionHelpers.h in CopyFiles */,
|
68C2155C1DE11AA80019C4BC /* ASObjectDescriptionHelpers.h in CopyFiles */,
|
||||||
@@ -967,7 +987,7 @@
|
|||||||
257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeTypes.h; path = TextKit/ASTextNodeTypes.h; sourceTree = "<group>"; };
|
257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeTypes.h; path = TextKit/ASTextNodeTypes.h; sourceTree = "<group>"; };
|
||||||
257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = "<group>"; };
|
257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = "<group>"; };
|
||||||
25E327541C16819500A2170C /* ASPagerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASPagerNode.h; sourceTree = "<group>"; };
|
25E327541C16819500A2170C /* ASPagerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASPagerNode.h; sourceTree = "<group>"; };
|
||||||
25E327551C16819500A2170C /* ASPagerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASPagerNode.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
|
25E327551C16819500A2170C /* ASPagerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASPagerNode.m; sourceTree = "<group>"; };
|
||||||
2911485B1A77147A005D0878 /* ASControlNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlNodeTests.m; sourceTree = "<group>"; };
|
2911485B1A77147A005D0878 /* ASControlNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlNodeTests.m; sourceTree = "<group>"; };
|
||||||
292C59991A956527007E5DD6 /* ASLayoutRangeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutRangeType.h; sourceTree = "<group>"; };
|
292C59991A956527007E5DD6 /* ASLayoutRangeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutRangeType.h; sourceTree = "<group>"; };
|
||||||
2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASBasicImageDownloaderInternal.h; sourceTree = "<group>"; };
|
2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASBasicImageDownloaderInternal.h; sourceTree = "<group>"; };
|
||||||
@@ -1158,15 +1178,23 @@
|
|||||||
CC512B841DAC45C60054848E /* ASTableView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASTableView+Undeprecated.h"; sourceTree = "<group>"; };
|
CC512B841DAC45C60054848E /* ASTableView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASTableView+Undeprecated.h"; sourceTree = "<group>"; };
|
||||||
CC54A81B1D70077A00296A24 /* ASDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASDispatch.h; sourceTree = "<group>"; };
|
CC54A81B1D70077A00296A24 /* ASDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASDispatch.h; sourceTree = "<group>"; };
|
||||||
CC54A81D1D7008B300296A24 /* ASDispatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDispatchTests.m; sourceTree = "<group>"; };
|
CC54A81D1D7008B300296A24 /* ASDispatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDispatchTests.m; sourceTree = "<group>"; };
|
||||||
|
CC6363E11E32C00800D8A8DE /* ASCollectionInteropProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionInteropProtocols.h; sourceTree = "<group>"; };
|
||||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
||||||
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = "<group>"; };
|
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = "<group>"; };
|
||||||
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = "<group>"; };
|
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = "<group>"; };
|
||||||
|
CC8525131E3FC253008EABE6 /* _ASCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCollectionViewCell.h; sourceTree = "<group>"; };
|
||||||
|
CC8525141E3FC253008EABE6 /* _ASCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _ASCollectionViewCell.m; sourceTree = "<group>"; };
|
||||||
CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASCellNode+Internal.h"; path = "AsyncDisplayKit/ASCellNode+Internal.h"; sourceTree = SOURCE_ROOT; };
|
CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASCellNode+Internal.h"; path = "AsyncDisplayKit/ASCellNode+Internal.h"; sourceTree = SOURCE_ROOT; };
|
||||||
CC8B05D41D73836400F54286 /* ASPerformanceTestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPerformanceTestContext.h; sourceTree = "<group>"; };
|
CC8B05D41D73836400F54286 /* ASPerformanceTestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPerformanceTestContext.h; sourceTree = "<group>"; };
|
||||||
CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPerformanceTestContext.m; sourceTree = "<group>"; };
|
CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPerformanceTestContext.m; sourceTree = "<group>"; };
|
||||||
CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodePerformanceTests.m; sourceTree = "<group>"; };
|
CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodePerformanceTests.m; sourceTree = "<group>"; };
|
||||||
CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewControllerTests.m; sourceTree = "<group>"; };
|
CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewControllerTests.m; sourceTree = "<group>"; };
|
||||||
CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeSnapshotTests.m; sourceTree = "<group>"; };
|
CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeSnapshotTests.m; sourceTree = "<group>"; };
|
||||||
|
CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSectionController.h; sourceTree = "<group>"; };
|
||||||
|
CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListAdapter+AsyncDisplayKit.h"; sourceTree = "<group>"; };
|
||||||
|
CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListAdapter+AsyncDisplayKit.m"; sourceTree = "<group>"; };
|
||||||
|
CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSupplementaryNodeSource.h; sourceTree = "<group>"; };
|
||||||
|
CCF92DCC1E3155180019E9C6 /* ASIGListKitMethodImplementations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIGListKitMethodImplementations.h; sourceTree = "<group>"; };
|
||||||
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
|
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = "<group>"; };
|
D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = "<group>"; };
|
||||||
D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = "<group>"; };
|
D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = "<group>"; };
|
||||||
@@ -1316,6 +1344,7 @@
|
|||||||
058D09B1195D04C000B7D73C /* AsyncDisplayKit */ = {
|
058D09B1195D04C000B7D73C /* AsyncDisplayKit */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CCE04B1D1E313E99006AEBBB /* Collection Data Adapter */,
|
||||||
DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */,
|
DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */,
|
||||||
DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */,
|
DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */,
|
||||||
92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */,
|
92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */,
|
||||||
@@ -1485,6 +1514,8 @@
|
|||||||
058D09E1195D050800B7D73C /* Details */ = {
|
058D09E1195D050800B7D73C /* Details */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CC8525131E3FC253008EABE6 /* _ASCollectionViewCell.h */,
|
||||||
|
CC8525141E3FC253008EABE6 /* _ASCollectionViewCell.m */,
|
||||||
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
|
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
|
||||||
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
|
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
|
||||||
058D09E4195D050800B7D73C /* _ASDisplayView.h */,
|
058D09E4195D050800B7D73C /* _ASDisplayView.h */,
|
||||||
@@ -1577,6 +1608,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6947B0BB1E36B4E30007C478 /* Layout */,
|
6947B0BB1E36B4E30007C478 /* Layout */,
|
||||||
|
CCE04B2A1E313EDA006AEBBB /* Collection Data Adapter */,
|
||||||
058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */,
|
058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */,
|
||||||
058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */,
|
058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */,
|
||||||
AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */,
|
AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */,
|
||||||
@@ -1784,6 +1816,34 @@
|
|||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
CCE04B1D1E313E99006AEBBB /* Collection Data Adapter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */,
|
||||||
|
CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */,
|
||||||
|
CCF92DCE1E315FC50019E9C6 /* IGListKit Support */,
|
||||||
|
);
|
||||||
|
name = "Collection Data Adapter";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CCE04B2A1E313EDA006AEBBB /* Collection Data Adapter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC6363E11E32C00800D8A8DE /* ASCollectionInteropProtocols.h */,
|
||||||
|
);
|
||||||
|
name = "Collection Data Adapter";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
CCF92DCE1E315FC50019E9C6 /* IGListKit Support */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CCF92DCC1E3155180019E9C6 /* ASIGListKitMethodImplementations.h */,
|
||||||
|
CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */,
|
||||||
|
CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */,
|
||||||
|
);
|
||||||
|
name = "IGListKit Support";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DE89C1691DCEB9CC00D49D74 /* Debug */ = {
|
DE89C1691DCEB9CC00D49D74 /* Debug */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1855,11 +1915,13 @@
|
|||||||
254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */,
|
254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */,
|
||||||
A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */,
|
A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */,
|
||||||
254C6B7A1BF94DF4003EC431 /* ASTextKitRenderer.h in Headers */,
|
254C6B7A1BF94DF4003EC431 /* ASTextKitRenderer.h in Headers */,
|
||||||
|
CCE04B1F1E313EA7006AEBBB /* ASSectionController.h in Headers */,
|
||||||
69CB62AC1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */,
|
69CB62AC1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */,
|
||||||
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */,
|
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */,
|
||||||
254C6B7C1BF94DF4003EC431 /* ASTextKitRenderer+TextChecking.h in Headers */,
|
254C6B7C1BF94DF4003EC431 /* ASTextKitRenderer+TextChecking.h in Headers */,
|
||||||
34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */,
|
34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */,
|
||||||
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */,
|
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */,
|
||||||
|
CCE04B221E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h in Headers */,
|
||||||
B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */,
|
B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */,
|
||||||
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
|
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
|
||||||
B35062461B010EFD0018CF92 /* ASBasicImageDownloaderInternal.h in Headers */,
|
B35062461B010EFD0018CF92 /* ASBasicImageDownloaderInternal.h in Headers */,
|
||||||
@@ -1883,6 +1945,7 @@
|
|||||||
9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */,
|
9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */,
|
||||||
B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */,
|
B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */,
|
||||||
6947B0C31E36B5040007C478 /* ASStackPositionedLayout.h in Headers */,
|
6947B0C31E36B5040007C478 /* ASStackPositionedLayout.h in Headers */,
|
||||||
|
CC6363E21E32C00800D8A8DE /* ASCollectionInteropProtocols.h in Headers */,
|
||||||
B35061F81B010EFD0018CF92 /* ASControlNode.h in Headers */,
|
B35061F81B010EFD0018CF92 /* ASControlNode.h in Headers */,
|
||||||
B35062171B010EFD0018CF92 /* ASDataController.h in Headers */,
|
B35062171B010EFD0018CF92 /* ASDataController.h in Headers */,
|
||||||
34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */,
|
34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */,
|
||||||
@@ -1901,6 +1964,7 @@
|
|||||||
B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */,
|
B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */,
|
||||||
B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */,
|
B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */,
|
||||||
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */,
|
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */,
|
||||||
|
CCF92DCD1E3155180019E9C6 /* ASIGListKitMethodImplementations.h in Headers */,
|
||||||
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
|
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
|
||||||
B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */,
|
B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */,
|
||||||
254C6B7F1BF94DF4003EC431 /* ASTextKitTruncating.h in Headers */,
|
254C6B7F1BF94DF4003EC431 /* ASTextKitTruncating.h in Headers */,
|
||||||
@@ -1935,6 +1999,7 @@
|
|||||||
DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */,
|
DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */,
|
||||||
B35062241B010EFD0018CF92 /* ASMutableAttributedStringBuilder.h in Headers */,
|
B35062241B010EFD0018CF92 /* ASMutableAttributedStringBuilder.h in Headers */,
|
||||||
B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */,
|
B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */,
|
||||||
|
CCE04B2C1E314A32006AEBBB /* ASSupplementaryNodeSource.h in Headers */,
|
||||||
8BBBAB8C1CEBAF1700107FC6 /* ASDefaultPlaybackButton.h in Headers */,
|
8BBBAB8C1CEBAF1700107FC6 /* ASDefaultPlaybackButton.h in Headers */,
|
||||||
B35062061B010EFD0018CF92 /* ASNetworkImageNode.h in Headers */,
|
B35062061B010EFD0018CF92 /* ASNetworkImageNode.h in Headers */,
|
||||||
34EFC76C1B701CED00AD841F /* ASOverlayLayoutSpec.h in Headers */,
|
34EFC76C1B701CED00AD841F /* ASOverlayLayoutSpec.h in Headers */,
|
||||||
@@ -1973,6 +2038,7 @@
|
|||||||
9C6BB3B31B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h in Headers */,
|
9C6BB3B31B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h in Headers */,
|
||||||
34EFC7731B701D0700AD841F /* ASAbsoluteLayoutSpec.h in Headers */,
|
34EFC7731B701D0700AD841F /* ASAbsoluteLayoutSpec.h in Headers */,
|
||||||
254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */,
|
254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */,
|
||||||
|
CC8525151E3FC253008EABE6 /* _ASCollectionViewCell.h in Headers */,
|
||||||
B350620A1B010EFD0018CF92 /* ASTableView.h in Headers */,
|
B350620A1B010EFD0018CF92 /* ASTableView.h in Headers */,
|
||||||
B350620C1B010EFD0018CF92 /* ASTableViewProtocols.h in Headers */,
|
B350620C1B010EFD0018CF92 /* ASTableViewProtocols.h in Headers */,
|
||||||
B350620D1B010EFD0018CF92 /* ASTextNode.h in Headers */,
|
B350620D1B010EFD0018CF92 /* ASTextNode.h in Headers */,
|
||||||
@@ -2227,6 +2293,7 @@
|
|||||||
AC6456091B0A335000CF11B8 /* ASCellNode.mm in Sources */,
|
AC6456091B0A335000CF11B8 /* ASCellNode.mm in Sources */,
|
||||||
DE8BEAC31C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
|
DE8BEAC31C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
|
||||||
ACF6ED1D1B17843500DA7C62 /* ASCenterLayoutSpec.mm in Sources */,
|
ACF6ED1D1B17843500DA7C62 /* ASCenterLayoutSpec.mm in Sources */,
|
||||||
|
CC8525161E3FC253008EABE6 /* _ASCollectionViewCell.m in Sources */,
|
||||||
9F98C0251DBDF2A300476D92 /* ASControlTargetAction.m in Sources */,
|
9F98C0251DBDF2A300476D92 /* ASControlTargetAction.m in Sources */,
|
||||||
18C2ED801B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */,
|
18C2ED801B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */,
|
||||||
92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */,
|
92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */,
|
||||||
@@ -2274,6 +2341,7 @@
|
|||||||
AC6145431D8AFD4F003D62A2 /* ASSection.m in Sources */,
|
AC6145431D8AFD4F003D62A2 /* ASSection.m in Sources */,
|
||||||
058D0A1B195D050800B7D73C /* ASMutableAttributedStringBuilder.m in Sources */,
|
058D0A1B195D050800B7D73C /* ASMutableAttributedStringBuilder.m in Sources */,
|
||||||
055B9FA91A1C154B00035D6D /* ASNetworkImageNode.mm in Sources */,
|
055B9FA91A1C154B00035D6D /* ASNetworkImageNode.mm in Sources */,
|
||||||
|
CCE04B231E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m in Sources */,
|
||||||
AEB7B01B1C5962EA00662EF4 /* ASDefaultPlayButton.m in Sources */,
|
AEB7B01B1C5962EA00662EF4 /* ASDefaultPlayButton.m in Sources */,
|
||||||
CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
||||||
ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */,
|
ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */,
|
||||||
@@ -2418,6 +2486,7 @@
|
|||||||
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
|
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
|
||||||
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */,
|
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */,
|
||||||
B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */,
|
B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */,
|
||||||
|
CC8525171E3FC253008EABE6 /* _ASCollectionViewCell.m in Sources */,
|
||||||
B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */,
|
B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */,
|
||||||
AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */,
|
AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */,
|
||||||
34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */,
|
34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */,
|
||||||
@@ -2465,6 +2534,7 @@
|
|||||||
34EFC7681B701CDE00AD841F /* ASLayout.mm in Sources */,
|
34EFC7681B701CDE00AD841F /* ASLayout.mm in Sources */,
|
||||||
DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */,
|
DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */,
|
||||||
254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */,
|
254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */,
|
||||||
|
CCE04B241E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m in Sources */,
|
||||||
34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */,
|
34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */,
|
||||||
CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
||||||
254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */,
|
254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */,
|
||||||
|
|||||||
@@ -501,6 +501,16 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*/
|
*/
|
||||||
- (nullable id<ASSectionContext>)collectionNode:(ASCollectionNode *)collectionNode contextForSection:(NSInteger)section;
|
- (nullable id<ASSectionContext>)collectionNode:(ASCollectionNode *)collectionNode contextForSection:(NSInteger)section;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks the data source to provide an array of supplementary element kinds that exist in a given section.
|
||||||
|
*
|
||||||
|
* @param collectionNode The sender.
|
||||||
|
* @param section The index of the section to provide supplementary kinds for.
|
||||||
|
*
|
||||||
|
* @return The supplementary element kinds that exist in the given section, if any.
|
||||||
|
*/
|
||||||
|
- (NSArray<NSString *> *)collectionNode:(ASCollectionNode *)collectionNode supplementaryElementKindsInSection:(NSInteger)section;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to -collectionView:cellForItemAtIndexPath:.
|
* Similar to -collectionView:cellForItemAtIndexPath:.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#import "ASCollectionInternal.h"
|
#import "ASCollectionInternal.h"
|
||||||
#import "ASCollectionViewLayoutFacilitatorProtocol.h"
|
#import "ASCollectionViewLayoutFacilitatorProtocol.h"
|
||||||
#import "ASCollectionNode.h"
|
#import "ASCollectionNode.h"
|
||||||
|
#import "ASCollectionNode+Beta.h"
|
||||||
#import "ASDisplayNode+Subclasses.h"
|
#import "ASDisplayNode+Subclasses.h"
|
||||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||||
#import "ASEnvironmentInternal.h"
|
#import "ASEnvironmentInternal.h"
|
||||||
|
|||||||
@@ -8,12 +8,18 @@
|
|||||||
// of patent rights can be found in the PATENTS file in the same directory.
|
// of patent rights can be found in the PATENTS file in the same directory.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#import "ASCollectionView.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#import "_ASCollectionViewCell.h"
|
||||||
#import "ASAssert.h"
|
#import "ASAssert.h"
|
||||||
#import "ASAvailability.h"
|
#import "ASAvailability.h"
|
||||||
#import "ASBatchFetching.h"
|
#import "ASBatchFetching.h"
|
||||||
#import "ASDelegateProxy.h"
|
#import "ASDelegateProxy.h"
|
||||||
#import "ASCellNode+Internal.h"
|
#import "ASCellNode+Internal.h"
|
||||||
#import "ASCollectionDataController.h"
|
#import "ASCollectionDataController.h"
|
||||||
|
#import "ASCollectionInternal.h"
|
||||||
#import "ASCollectionViewLayoutController.h"
|
#import "ASCollectionViewLayoutController.h"
|
||||||
#import "ASCollectionViewFlowLayoutInspector.h"
|
#import "ASCollectionViewFlowLayoutInspector.h"
|
||||||
#import "ASDisplayNodeExtras.h"
|
#import "ASDisplayNodeExtras.h"
|
||||||
@@ -27,6 +33,7 @@
|
|||||||
#import "ASSectionContext.h"
|
#import "ASSectionContext.h"
|
||||||
#import "ASCollectionView+Undeprecated.h"
|
#import "ASCollectionView+Undeprecated.h"
|
||||||
#import "_ASHierarchyChangeSet.h"
|
#import "_ASHierarchyChangeSet.h"
|
||||||
|
#import "ASCollectionInteropProtocols.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A macro to get self.collectionNode and assign it to a local variable, or return
|
* A macro to get self.collectionNode and assign it to a local variable, or return
|
||||||
@@ -62,79 +69,6 @@ static const NSUInteger kASCollectionViewAnimationNone = UITableViewRowAnimation
|
|||||||
/// Used for all cells and supplementaries. UICV keys by supp-kind+reuseID so this is plenty.
|
/// Used for all cells and supplementaries. UICV keys by supp-kind+reuseID so this is plenty.
|
||||||
static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
||||||
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark ASCellNode<->UICollectionViewCell bridging.
|
|
||||||
|
|
||||||
@class _ASCollectionViewCell;
|
|
||||||
|
|
||||||
@interface _ASCollectionViewCell : UICollectionViewCell
|
|
||||||
@property (nonatomic, weak) ASCellNode *node;
|
|
||||||
@property (nonatomic, strong) UICollectionViewLayoutAttributes *layoutAttributes;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation _ASCollectionViewCell
|
|
||||||
|
|
||||||
- (void)setNode:(ASCellNode *)node
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertMainThread();
|
|
||||||
node.layoutAttributes = _layoutAttributes;
|
|
||||||
_node = node;
|
|
||||||
self.backgroundColor = node.backgroundColor;
|
|
||||||
self.clipsToBounds = node.clipsToBounds;
|
|
||||||
[node __setSelectedFromUIKit:self.selected];
|
|
||||||
[node __setHighlightedFromUIKit:self.highlighted];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setSelected:(BOOL)selected
|
|
||||||
{
|
|
||||||
[super setSelected:selected];
|
|
||||||
[_node __setSelectedFromUIKit:selected];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted
|
|
||||||
{
|
|
||||||
[super setHighlighted:highlighted];
|
|
||||||
[_node __setHighlightedFromUIKit:highlighted];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
|
||||||
{
|
|
||||||
_layoutAttributes = layoutAttributes;
|
|
||||||
_node.layoutAttributes = layoutAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)prepareForReuse
|
|
||||||
{
|
|
||||||
self.layoutAttributes = nil;
|
|
||||||
|
|
||||||
// Need to clear node pointer before UIKit calls setSelected:NO / setHighlighted:NO on its cells
|
|
||||||
self.node = nil;
|
|
||||||
[super prepareForReuse];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In the initial case, this is called by UICollectionView during cell dequeueing, before
|
|
||||||
* we get a chance to assign a node to it, so we must be sure to set these layout attributes
|
|
||||||
* on our node when one is next assigned to us in @c setNode: . Since there may be cases when we _do_ already
|
|
||||||
* have our node assigned e.g. during a layout update for existing cells, we also attempt
|
|
||||||
* to update it now.
|
|
||||||
*/
|
|
||||||
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
|
||||||
{
|
|
||||||
self.layoutAttributes = layoutAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep our node filling our content view.
|
|
||||||
*/
|
|
||||||
- (void)layoutSubviews
|
|
||||||
{
|
|
||||||
[super layoutSubviews];
|
|
||||||
self.node.frame = self.contentView.bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark ASCollectionView.
|
#pragma mark ASCollectionView.
|
||||||
|
|
||||||
@@ -243,8 +177,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
unsigned int collectionNodeWillBeginBatchFetch:1;
|
unsigned int collectionNodeWillBeginBatchFetch:1;
|
||||||
unsigned int collectionNodeWillDisplaySupplementaryElement:1;
|
unsigned int collectionNodeWillDisplaySupplementaryElement:1;
|
||||||
unsigned int collectionNodeDidEndDisplayingSupplementaryElement:1;
|
unsigned int collectionNodeDidEndDisplayingSupplementaryElement:1;
|
||||||
|
|
||||||
unsigned int shouldBatchFetchForCollectionNode:1;
|
unsigned int shouldBatchFetchForCollectionNode:1;
|
||||||
|
// Whether this delegate conforms to ASCollectionDataSourceInterop
|
||||||
|
unsigned int interop:1;
|
||||||
} _asyncDelegateFlags;
|
} _asyncDelegateFlags;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -256,9 +191,13 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
unsigned int collectionNodeNodeForItem:1;
|
unsigned int collectionNodeNodeForItem:1;
|
||||||
unsigned int collectionNodeNodeBlockForItem:1;
|
unsigned int collectionNodeNodeBlockForItem:1;
|
||||||
unsigned int collectionNodeNodeForSupplementaryElement:1;
|
unsigned int collectionNodeNodeForSupplementaryElement:1;
|
||||||
|
unsigned int collectionNodeSupplementaryElementKindsInSection:1;
|
||||||
unsigned int numberOfSectionsInCollectionNode:1;
|
unsigned int numberOfSectionsInCollectionNode:1;
|
||||||
unsigned int collectionNodeNumberOfItemsInSection:1;
|
unsigned int collectionNodeNumberOfItemsInSection:1;
|
||||||
unsigned int collectionNodeContextForSection:1;
|
unsigned int collectionNodeContextForSection:1;
|
||||||
|
|
||||||
|
// Whether this data source conforms to ASCollectionDataSourceInterop
|
||||||
|
unsigned int interop:1;
|
||||||
} _asyncDataSourceFlags;
|
} _asyncDataSourceFlags;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -267,8 +206,6 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
} _layoutInspectorFlags;
|
} _layoutInspectorFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, weak) ASCollectionNode *collectionNode;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASCollectionNode ()
|
@interface ASCollectionNode ()
|
||||||
@@ -426,14 +363,14 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
|
|
||||||
- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource
|
- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource
|
||||||
{
|
{
|
||||||
// UIKit can internally generate a call to this method upon changing the asyncDataSource; only assert for non-nil.
|
// UIKit can internally generate a call to this method upon changing the asyncDataSource; only assert for non-nil. We also allow this when we're doing interop.
|
||||||
ASDisplayNodeAssert(dataSource == nil, @"ASCollectionView uses asyncDataSource, not UICollectionView's dataSource property.");
|
ASDisplayNodeAssert(_asyncDelegateFlags.interop || dataSource == nil, @"ASCollectionView uses asyncDataSource, not UICollectionView's dataSource property.");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
|
- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
|
||||||
{
|
{
|
||||||
// Our UIScrollView superclass sets its delegate to nil on dealloc. Only assert if we get a non-nil value here.
|
// Our UIScrollView superclass sets its delegate to nil on dealloc. Only assert if we get a non-nil value here. We also allow this when we're doing interop.
|
||||||
ASDisplayNodeAssert(delegate == nil, @"ASCollectionView uses asyncDelegate, not UICollectionView's delegate property.");
|
ASDisplayNodeAssert(_asyncDelegateFlags.interop || delegate == nil, @"ASCollectionView uses asyncDelegate, not UICollectionView's delegate property.");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy
|
- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy
|
||||||
@@ -464,8 +401,8 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
if (asyncDataSource == nil) {
|
if (asyncDataSource == nil) {
|
||||||
_asyncDataSource = nil;
|
_asyncDataSource = nil;
|
||||||
_proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
_proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
||||||
|
_asyncDataSourceFlags = {};
|
||||||
memset(&_asyncDataSourceFlags, 0, sizeof(_asyncDataSourceFlags));
|
|
||||||
} else {
|
} else {
|
||||||
_asyncDataSource = asyncDataSource;
|
_asyncDataSource = asyncDataSource;
|
||||||
_proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self];
|
_proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self];
|
||||||
@@ -482,7 +419,8 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:numberOfItemsInSection:)];
|
_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:numberOfItemsInSection:)];
|
||||||
_asyncDataSourceFlags.collectionNodeContextForSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:contextForSection:)];
|
_asyncDataSourceFlags.collectionNodeContextForSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:contextForSection:)];
|
||||||
_asyncDataSourceFlags.collectionNodeNodeForSupplementaryElement = [_asyncDataSource respondsToSelector:@selector(collectionNode:nodeForSupplementaryElementOfKind:atIndexPath:)];
|
_asyncDataSourceFlags.collectionNodeNodeForSupplementaryElement = [_asyncDataSource respondsToSelector:@selector(collectionNode:nodeForSupplementaryElementOfKind:atIndexPath:)];
|
||||||
|
_asyncDataSourceFlags.collectionNodeSupplementaryElementKindsInSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:supplementaryElementKindsInSection:)];
|
||||||
|
_asyncDataSourceFlags.interop = [_asyncDataSource conformsToProtocol:@protocol(ASCollectionDataSourceInterop)];
|
||||||
|
|
||||||
ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection || _asyncDataSourceFlags.collectionViewNumberOfItemsInSection, @"Data source must implement collectionNode:numberOfItemsInSection:");
|
ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection || _asyncDataSourceFlags.collectionViewNumberOfItemsInSection, @"Data source must implement collectionNode:numberOfItemsInSection:");
|
||||||
ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNodeBlockForItem
|
ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNodeBlockForItem
|
||||||
@@ -520,8 +458,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
if (asyncDelegate == nil) {
|
if (asyncDelegate == nil) {
|
||||||
_asyncDelegate = nil;
|
_asyncDelegate = nil;
|
||||||
_proxyDelegate = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
_proxyDelegate = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
||||||
|
_asyncDataSourceFlags = {};
|
||||||
memset(&_asyncDelegateFlags, 0, sizeof(_asyncDelegateFlags));
|
|
||||||
} else {
|
} else {
|
||||||
_asyncDelegate = asyncDelegate;
|
_asyncDelegate = asyncDelegate;
|
||||||
_proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self];
|
_proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self];
|
||||||
@@ -561,6 +498,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
_asyncDelegateFlags.collectionNodeShouldShowMenuForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldShowMenuForItemAtIndexPath:)];
|
_asyncDelegateFlags.collectionNodeShouldShowMenuForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldShowMenuForItemAtIndexPath:)];
|
||||||
_asyncDelegateFlags.collectionNodeCanPerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:canPerformAction:forItemAtIndexPath:sender:)];
|
_asyncDelegateFlags.collectionNodeCanPerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:canPerformAction:forItemAtIndexPath:sender:)];
|
||||||
_asyncDelegateFlags.collectionNodePerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:performAction:forItemAtIndexPath:sender:)];
|
_asyncDelegateFlags.collectionNodePerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:performAction:forItemAtIndexPath:sender:)];
|
||||||
|
_asyncDelegateFlags.interop = [_asyncDelegate conformsToProtocol:@protocol(ASCollectionDelegateInterop)];
|
||||||
}
|
}
|
||||||
|
|
||||||
super.delegate = (id<UICollectionViewDelegate>)_proxyDelegate;
|
super.delegate = (id<UICollectionViewDelegate>)_proxyDelegate;
|
||||||
@@ -939,7 +877,13 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
|
|
||||||
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
UICollectionReusableView *view = [self dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:kReuseIdentifier forIndexPath:indexPath];
|
UICollectionReusableView *view;
|
||||||
|
if (_asyncDataSource && _asyncDataSourceFlags.interop) {
|
||||||
|
view = [(id<ASCollectionDataSourceInterop>)_asyncDataSource collectionView:collectionView viewForSupplementaryElementOfKind:kind atIndexPath:indexPath];
|
||||||
|
} else {
|
||||||
|
view = [self dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:kReuseIdentifier forIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
ASCellNode *node = [_dataController supplementaryNodeOfKind:kind atIndexPath:indexPath];
|
ASCellNode *node = [_dataController supplementaryNodeOfKind:kind atIndexPath:indexPath];
|
||||||
ASDisplayNodeAssert(node != nil, @"Supplementary node should exist. Kind = %@, indexPath = %@, collectionDataSource = %@", kind, indexPath, self);
|
ASDisplayNodeAssert(node != nil, @"Supplementary node should exist. Kind = %@, indexPath = %@, collectionDataSource = %@", kind, indexPath, self);
|
||||||
[_rangeController configureContentView:view forCellNode:node];
|
[_rangeController configureContentView:view forCellNode:node];
|
||||||
@@ -948,7 +892,12 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
|
|
||||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
_ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:kReuseIdentifier forIndexPath:indexPath];
|
_ASCollectionViewCell *cell;
|
||||||
|
if (_asyncDataSource && _asyncDataSourceFlags.interop) {
|
||||||
|
cell = [(id<ASCollectionDataSourceInterop>)_asyncDataSource collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
} else {
|
||||||
|
cell = [self dequeueReusableCellWithReuseIdentifier:kReuseIdentifier forIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
ASCellNode *node = [self nodeForItemAtIndexPath:indexPath];
|
ASCellNode *node = [self nodeForItemAtIndexPath:indexPath];
|
||||||
cell.node = node;
|
cell.node = node;
|
||||||
@@ -979,7 +928,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
|
|
||||||
ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with cell that will be displayed not to be nil. indexPath: %@", indexPath);
|
ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with cell that will be displayed not to be nil. indexPath: %@", indexPath);
|
||||||
|
|
||||||
if (_asyncDelegateFlags.collectionNodeWillDisplayItem) {
|
if (_asyncDelegateFlags.interop) {
|
||||||
|
[(id<ASCollectionDelegateInterop>)_asyncDelegate collectionView:collectionView willDisplayCell:cell forItemAtIndexPath:indexPath];
|
||||||
|
} else if (_asyncDelegateFlags.collectionNodeWillDisplayItem) {
|
||||||
if (ASCollectionNode *collectionNode = self.collectionNode) {
|
if (ASCollectionNode *collectionNode = self.collectionNode) {
|
||||||
[_asyncDelegate collectionNode:collectionNode willDisplayItemWithNode:cellNode];
|
[_asyncDelegate collectionNode:collectionNode willDisplayItemWithNode:cellNode];
|
||||||
}
|
}
|
||||||
@@ -1004,7 +955,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
ASCellNode *cellNode = [cell node];
|
ASCellNode *cellNode = [cell node];
|
||||||
ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with removed cell not to be nil.");
|
ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with removed cell not to be nil.");
|
||||||
|
|
||||||
if (_asyncDelegateFlags.collectionNodeDidEndDisplayingItem) {
|
if (_asyncDelegateFlags.interop) {
|
||||||
|
[(id<ASCollectionDelegateInterop>)_asyncDelegate collectionView:collectionView didEndDisplayingCell:cell forItemAtIndexPath:indexPath];
|
||||||
|
} else if (_asyncDelegateFlags.collectionNodeDidEndDisplayingItem) {
|
||||||
if (ASCollectionNode *collectionNode = self.collectionNode) {
|
if (ASCollectionNode *collectionNode = self.collectionNode) {
|
||||||
[_asyncDelegate collectionNode:collectionNode didEndDisplayingItemWithNode:cellNode];
|
[_asyncDelegate collectionNode:collectionNode didEndDisplayingItemWithNode:cellNode];
|
||||||
}
|
}
|
||||||
@@ -1544,10 +1497,20 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Lock this
|
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController sections:(NSIndexSet *)sections
|
||||||
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController
|
|
||||||
{
|
{
|
||||||
return [_registeredSupplementaryKinds allObjects];
|
if (_asyncDataSourceFlags.collectionNodeSupplementaryElementKindsInSection) {
|
||||||
|
NSMutableSet *kinds = [NSMutableSet set];
|
||||||
|
GET_COLLECTIONNODE_OR_RETURN(collectionNode, @[]);
|
||||||
|
[sections enumerateIndexesUsingBlock:^(NSUInteger section, BOOL * _Nonnull stop) {
|
||||||
|
NSArray *kindsForSection = [_asyncDataSource collectionNode:collectionNode supplementaryElementKindsInSection:section];
|
||||||
|
[kinds addObjectsFromArray:kindsForSection];
|
||||||
|
}];
|
||||||
|
return [kinds allObjects];
|
||||||
|
} else {
|
||||||
|
// TODO: Lock this
|
||||||
|
return [_registeredSupplementaryKinds allObjects];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASSizeRange)dataController:(ASCollectionDataController *)dataController constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)dataController:(ASCollectionDataController *)dataController constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Implement -numberOfSectionsInCollectionNode: instead.");
|
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Implement -numberOfSectionsInCollectionNode: instead.");
|
||||||
|
|
||||||
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement - collectionNode:viewForSupplementaryElementOfKind:atIndexPath: instead.");
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement - collectionNode:nodeForSupplementaryElementOfKind:atIndexPath: instead.");
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -389,11 +389,10 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
if ([self _isNodeLoaded]) {
|
if ([self _isNodeLoaded]) {
|
||||||
ASDisplayNodeFailAssert(@"Attempt to call %@ on node after it was loaded. Node: %@", NSStringFromSelector(_cmd), self);
|
ASDisplayNodeAssertThreadAffinity(self);
|
||||||
return;
|
ASDN::MutexUnlocker l(__instanceLock__);
|
||||||
}
|
body(self);
|
||||||
|
} else if (_onDidLoadBlocks == nil) {
|
||||||
if (_onDidLoadBlocks == nil) {
|
|
||||||
_onDidLoadBlocks = [NSMutableArray arrayWithObject:body];
|
_onDidLoadBlocks = [NSMutableArray arrayWithObject:body];
|
||||||
} else {
|
} else {
|
||||||
[_onDidLoadBlocks addObject:body];
|
[_onDidLoadBlocks addObject:body];
|
||||||
@@ -663,11 +662,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
|
|
||||||
ASDisplayNodeLogEvent(self, @"didLoad");
|
ASDisplayNodeLogEvent(self, @"didLoad");
|
||||||
|
[self didLoad];
|
||||||
for (ASDisplayNodeDidLoadBlock block in _onDidLoadBlocks) {
|
for (ASDisplayNodeDidLoadBlock block in _onDidLoadBlocks) {
|
||||||
block(self);
|
block(self);
|
||||||
}
|
}
|
||||||
_onDidLoadBlocks = nil;
|
_onDidLoadBlocks = nil;
|
||||||
[self didLoad];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didLoad
|
- (void)didLoad
|
||||||
|
|||||||
66
AsyncDisplayKit/ASIGListKitMethodImplementations.h
Normal file
66
AsyncDisplayKit/ASIGListKitMethodImplementations.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// ASIGListKitMethodImplementations.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you are using AsyncDisplayKit with IGListKit, you should use
|
||||||
|
* these macros to provide implementations of methods like
|
||||||
|
* -cellForItemAtIndex: that don't apply when used with AsyncDisplayKit.
|
||||||
|
*
|
||||||
|
* Your section controllers should also conform to @c ASSectionController and your
|
||||||
|
* supplementary view sources should conform to @c ASSupplementaryNodeSource.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/_ASCollectionViewCell.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation of viewForSupplementaryElementOfKind that connects
|
||||||
|
* IGSupplementaryViewSource to AsyncDisplayKit. Add this into the .m file
|
||||||
|
* for your `ASIGListSupplementaryViewSource` and implement the ASDK-specific
|
||||||
|
* method `nodeForSupplementaryElementOfKind:` to provide your node.
|
||||||
|
*
|
||||||
|
* @param sectionController The section controller this supplementary source is
|
||||||
|
* working on behalf of. For example, `self` or `self.sectionController`.
|
||||||
|
*/
|
||||||
|
#define ASIGSupplementarySourceViewForSupplementaryElementImplementation(sectionController) \
|
||||||
|
- (__kindof UICollectionReusableView *)viewForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index { \
|
||||||
|
return [self.collectionContext dequeueReusableSupplementaryViewOfKind:elementKind forSectionController:sectionController class:[UICollectionReusableView class] atIndex:index]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation of sizeForSupplementaryViewOfKind that connects
|
||||||
|
* IGSupplementaryViewSource to AsyncDisplayKit. Add this into the .m file
|
||||||
|
* for your `ASIGListSupplementaryViewSource` and implement the ASDK-specific
|
||||||
|
* method `nodeForSupplementaryElementOfKind:` to provide your node which should
|
||||||
|
* size itself. You can set `node.style.preferredSize` if you want to fix the size.
|
||||||
|
*
|
||||||
|
* @param sectionController The section controller this supplementary source is
|
||||||
|
* working on behalf of. For example, `self` or `self.sectionController`.
|
||||||
|
*/
|
||||||
|
#define ASIGSupplementarySourceSizeForSupplementaryElementImplementation \
|
||||||
|
- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndex:(NSInteger)index {\
|
||||||
|
ASDisplayNodeFailAssert(@"Did not expect %@ to be called.", NSStringFromSelector(_cmd)); \
|
||||||
|
return CGSizeZero; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define ASIGSectionControllerCellForIndexImplementation \
|
||||||
|
- (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index\
|
||||||
|
{\
|
||||||
|
return [self.collectionContext dequeueReusableCellOfClass:[_ASCollectionViewCell class] forSectionController:self atIndex:index]; \
|
||||||
|
}\
|
||||||
|
|
||||||
|
#define ASIGSectionControllerSizeForItemImplementation \
|
||||||
|
- (CGSize)sizeForItemAtIndex:(NSInteger)index \
|
||||||
|
{\
|
||||||
|
ASDisplayNodeFailAssert(@"Did not expect %@ to be called.", NSStringFromSelector(_cmd)); \
|
||||||
|
return CGSizeZero;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IG_LIST_KIT
|
||||||
69
AsyncDisplayKit/ASSectionController.h
Normal file
69
AsyncDisplayKit/ASSectionController.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// ASSectionController.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A protocol that your section controllers should conform to,
|
||||||
|
* in addition to IGListSectionType, in order to be used with AsyncDisplayKit.
|
||||||
|
*
|
||||||
|
* @note Your supplementary view source should conform to @c ASSupplementaryNodeSource.
|
||||||
|
*/
|
||||||
|
@protocol ASSectionController <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method to provide the node block for the item at the given index.
|
||||||
|
* The node block you return will be run asynchronously off the main thread,
|
||||||
|
* so it's important to retrieve any objects from your section _outside_ the block
|
||||||
|
* because by the time the block is run, the array may have changed.
|
||||||
|
*
|
||||||
|
* @param index The index of the item.
|
||||||
|
* @return A block to be run concurrently to build the node for this item.
|
||||||
|
* @see collectionNode:nodeBlockForItemAtIndexPath:
|
||||||
|
*/
|
||||||
|
- (ASCellNodeBlock)nodeBlockForItemAtIndex:(NSInteger)index;
|
||||||
|
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks the section controller whether it should batch fetch because the user is
|
||||||
|
* near the end of the current data set.
|
||||||
|
*
|
||||||
|
* @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of
|
||||||
|
* objects that can be fetched or no network connection.
|
||||||
|
*
|
||||||
|
* If not implemented, the assumed return value is @c YES.
|
||||||
|
*/
|
||||||
|
- (BOOL)shouldBatchFetch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks the section controller to begin fetching more content (tail loading) because
|
||||||
|
* the user is near the end of the current data set.
|
||||||
|
*
|
||||||
|
* @param context A context object that must be notified when the batch fetch is completed.
|
||||||
|
*
|
||||||
|
* @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future
|
||||||
|
* notifications to do batch fetches. This method is called on a background queue.
|
||||||
|
*/
|
||||||
|
- (void)beginBatchFetchWithContext:(ASBatchContext *)context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method to provide the size range used for measuring the item
|
||||||
|
* at the given index.
|
||||||
|
*
|
||||||
|
* @param index The index of the item.
|
||||||
|
* @return A size range used for asynchronously measuring the node at this index.
|
||||||
|
* @see collectionNode:constrainedSizeForItemAtIndexPath:
|
||||||
|
*/
|
||||||
|
- (ASSizeRange)sizeRangeForItemAtIndex:(NSInteger)index;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
40
AsyncDisplayKit/ASSupplementaryNodeSource.h
Normal file
40
AsyncDisplayKit/ASSupplementaryNodeSource.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// ASSupplementaryNodeSource.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol ASSupplementaryNodeSource <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method to provide the node for the item at the given index.
|
||||||
|
*
|
||||||
|
* @param elementKind The kind of supplementary element.
|
||||||
|
* @param index The index of the item.
|
||||||
|
* @return A node for the supplementary element.
|
||||||
|
* @see collectionNode:nodeForSupplementaryElementOfKind:atIndexPath:
|
||||||
|
*/
|
||||||
|
- (ASCellNode *)nodeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index;
|
||||||
|
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method to provide the size range used for measuring the supplementary
|
||||||
|
* element of the given kind at the given index.
|
||||||
|
*
|
||||||
|
* @param elementKind The kind of supplementary element.
|
||||||
|
* @param index The index of the item.
|
||||||
|
* @return A size range used for asynchronously measuring the node.
|
||||||
|
* @see collectionNode:constrainedSizeForSupplementaryElementOfKind:atIndexPath:
|
||||||
|
*/
|
||||||
|
- (ASSizeRange)sizeRangeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@@ -17,3 +17,7 @@
|
|||||||
// a user does not include the framework in the link binary with build step).
|
// a user does not include the framework in the link binary with build step).
|
||||||
#define PIN_REMOTE_IMAGE __has_include(<PINRemoteImage/PINRemoteImage.h>)
|
#define PIN_REMOTE_IMAGE __has_include(<PINRemoteImage/PINRemoteImage.h>)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef IG_LIST_KIT
|
||||||
|
#define IG_LIST_KIT __has_include(<IGListKit/IGListKit.h>)
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -34,6 +34,13 @@
|
|||||||
#import <AsyncDisplayKit/ASCellNode.h>
|
#import <AsyncDisplayKit/ASCellNode.h>
|
||||||
#import <AsyncDisplayKit/ASSectionContext.h>
|
#import <AsyncDisplayKit/ASSectionContext.h>
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/ASSectionController.h>
|
||||||
|
#import <AsyncDisplayKit/ASSupplementaryNodeSource.h>
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
#import <AsyncDisplayKit/IGListAdapter+AsyncDisplayKit.h>
|
||||||
|
#import <AsyncDisplayKit/ASIGListKitMethodImplementations.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#import <AsyncDisplayKit/ASScrollNode.h>
|
#import <AsyncDisplayKit/ASScrollNode.h>
|
||||||
|
|
||||||
#import <AsyncDisplayKit/ASPagerFlowLayout.h>
|
#import <AsyncDisplayKit/ASPagerFlowLayout.h>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*/
|
*/
|
||||||
- (ASSizeRange)dataController:(ASCollectionDataController *)dataController constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
- (ASSizeRange)dataController:(ASCollectionDataController *)dataController constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController;
|
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController sections:(NSIndexSet *)sections;
|
||||||
|
|
||||||
- (NSUInteger)dataController:(ASCollectionDataController *)dataController supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section;
|
- (NSUInteger)dataController:(ASCollectionDataController *)dataController supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#import "ASIndexedNodeContext.h"
|
#import "ASIndexedNodeContext.h"
|
||||||
#import "ASSection.h"
|
#import "ASSection.h"
|
||||||
#import "ASSectionContext.h"
|
#import "ASSectionContext.h"
|
||||||
|
#import "NSIndexSet+ASHelpers.h"
|
||||||
|
|
||||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||||
#define LOG(...)
|
#define LOG(...)
|
||||||
@@ -26,6 +27,13 @@
|
|||||||
NSInteger _nextSectionID;
|
NSInteger _nextSectionID;
|
||||||
NSMutableArray<ASSection *> *_sections;
|
NSMutableArray<ASSection *> *_sections;
|
||||||
NSArray<ASSection *> *_pendingSections;
|
NSArray<ASSection *> *_pendingSections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* supplementaryKinds can only be accessed on the main thread
|
||||||
|
* and so we set this in the -prepare stage, and then read it during the -will
|
||||||
|
* stage of each update operation.
|
||||||
|
*/
|
||||||
|
NSArray *_supplementaryKindsForPendingOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id<ASCollectionDataControllerSource>)collectionDataSource;
|
- (id<ASCollectionDataControllerSource>)collectionDataSource;
|
||||||
@@ -59,7 +67,7 @@
|
|||||||
[_sections removeAllObjects];
|
[_sections removeAllObjects];
|
||||||
[self _populatePendingSectionsFromDataSource:sections];
|
[self _populatePendingSectionsFromDataSource:sections];
|
||||||
|
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
for (NSString *kind in [self supplementaryKindsInSections:sections]) {
|
||||||
LOG(@"Populating elements of kind: %@", kind);
|
LOG(@"Populating elements of kind: %@", kind);
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||||
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableContexts:contexts];
|
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableContexts:contexts];
|
||||||
@@ -101,7 +109,7 @@
|
|||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
[self _populatePendingSectionsFromDataSource:sections];
|
[self _populatePendingSectionsFromDataSource:sections];
|
||||||
|
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
for (NSString *kind in [self supplementaryKindsInSections:sections]) {
|
||||||
LOG(@"Populating elements of kind: %@, for sections: %@", kind, sections);
|
LOG(@"Populating elements of kind: %@, for sections: %@", kind, sections);
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||||
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableContexts:contexts];
|
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableContexts:contexts];
|
||||||
@@ -127,46 +135,29 @@
|
|||||||
[_pendingNodeContexts removeAllObjects];
|
[_pendingNodeContexts removeAllObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)prepareForDeleteSections:(NSIndexSet *)sections
|
||||||
|
{
|
||||||
|
_supplementaryKindsForPendingOperation = [self supplementaryKindsInSections:sections];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)willDeleteSections:(NSIndexSet *)sections
|
- (void)willDeleteSections:(NSIndexSet *)sections
|
||||||
{
|
{
|
||||||
[_sections removeObjectsAtIndexes:sections];
|
[_sections removeObjectsAtIndexes:sections];
|
||||||
|
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
for (NSString *kind in _supplementaryKindsForPendingOperation) {
|
||||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections);
|
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections);
|
||||||
|
|
||||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||||
[self deleteSectionsOfKind:kind atIndexSet:sections completion:nil];
|
[self deleteSectionsOfKind:kind atIndexSet:sections completion:nil];
|
||||||
}
|
}
|
||||||
}
|
_supplementaryKindsForPendingOperation = nil;
|
||||||
|
|
||||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection
|
|
||||||
{
|
|
||||||
ASSection *movedSection = [_sections objectAtIndex:section];
|
|
||||||
[_sections removeObjectAtIndex:section];
|
|
||||||
[_sections insertObject:movedSection atIndex:newSection];
|
|
||||||
|
|
||||||
NSIndexSet *sectionAsIndexSet = [NSIndexSet indexSetWithIndex:section];
|
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
|
||||||
NSMutableArray *editingNodes = [self editingNodesOfKind:kind];
|
|
||||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(editingNodes, sectionAsIndexSet);
|
|
||||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(editingNodes, indexPaths);
|
|
||||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
|
||||||
|
|
||||||
// update the section of indexpaths
|
|
||||||
NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
|
||||||
for (NSIndexPath *indexPath in indexPaths) {
|
|
||||||
NSUInteger newItem = [indexPath indexAtPosition:indexPath.length - 1];
|
|
||||||
NSIndexPath *mappedIndexPath = [NSIndexPath indexPathForItem:newItem inSection:newSection];
|
|
||||||
[updatedIndexPaths addObject:mappedIndexPath];
|
|
||||||
}
|
|
||||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)prepareForInsertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
- (void)prepareForInsertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
NSIndexSet *sections = [NSIndexSet as_sectionsFromIndexPaths:indexPaths];
|
||||||
|
for (NSString *kind in [self supplementaryKindsInSections:sections]) {
|
||||||
LOG(@"Populating elements of kind: %@, for index paths: %@", kind, indexPaths);
|
LOG(@"Populating elements of kind: %@, for index paths: %@", kind, indexPaths);
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||||
[self _populateSupplementaryNodesOfKind:kind atIndexPaths:indexPaths mutableContexts:contexts];
|
[self _populateSupplementaryNodesOfKind:kind atIndexPaths:indexPaths mutableContexts:contexts];
|
||||||
@@ -188,7 +179,9 @@
|
|||||||
- (void)prepareForDeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
- (void)prepareForDeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
NSIndexSet *sections = [NSIndexSet as_sectionsFromIndexPaths:indexPaths];
|
||||||
|
_supplementaryKindsForPendingOperation = [self supplementaryKindsInSections:sections];
|
||||||
|
for (NSString *kind in _supplementaryKindsForPendingOperation) {
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||||
[self _populateSupplementaryNodesOfKind:kind atIndexPaths:indexPaths mutableContexts:contexts];
|
[self _populateSupplementaryNodesOfKind:kind atIndexPaths:indexPaths mutableContexts:contexts];
|
||||||
_pendingNodeContexts[kind] = contexts;
|
_pendingNodeContexts[kind] = contexts;
|
||||||
@@ -197,7 +190,7 @@
|
|||||||
|
|
||||||
- (void)willDeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
- (void)willDeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||||
{
|
{
|
||||||
for (NSString *kind in [self supplementaryKinds]) {
|
for (NSString *kind in _supplementaryKindsForPendingOperation) {
|
||||||
NSArray<NSIndexPath *> *deletedIndexPaths = ASIndexPathsInMultidimensionalArrayIntersectingIndexPaths([self editingNodesOfKind:kind], indexPaths);
|
NSArray<NSIndexPath *> *deletedIndexPaths = ASIndexPathsInMultidimensionalArrayIntersectingIndexPaths([self editingNodesOfKind:kind], indexPaths);
|
||||||
|
|
||||||
[self deleteNodesOfKind:kind atIndexPaths:deletedIndexPaths completion:nil];
|
[self deleteNodesOfKind:kind atIndexPaths:deletedIndexPaths completion:nil];
|
||||||
@@ -216,6 +209,7 @@
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
[_pendingNodeContexts removeAllObjects];
|
[_pendingNodeContexts removeAllObjects];
|
||||||
|
_supplementaryKindsForPendingOperation = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_populatePendingSectionsFromDataSource:(NSIndexSet *)sectionIndexes
|
- (void)_populatePendingSectionsFromDataSource:(NSIndexSet *)sectionIndexes
|
||||||
@@ -323,9 +317,9 @@
|
|||||||
|
|
||||||
#pragma mark - Private Helpers
|
#pragma mark - Private Helpers
|
||||||
|
|
||||||
- (NSArray *)supplementaryKinds
|
- (NSArray *)supplementaryKindsInSections:(NSIndexSet *)sections
|
||||||
{
|
{
|
||||||
return [self.collectionDataSource supplementaryNodeKindsInDataController:self];
|
return [self.collectionDataSource supplementaryNodeKindsInDataController:self sections:sections];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id<ASCollectionDataControllerSource>)collectionDataSource
|
- (id<ASCollectionDataControllerSource>)collectionDataSource
|
||||||
|
|||||||
@@ -66,24 +66,32 @@
|
|||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
|
ASSizeRange result = ASSizeRangeUnconstrained;
|
||||||
if (_delegateFlags.implementsConstrainedSizeForItemAtIndexPath) {
|
if (_delegateFlags.implementsConstrainedSizeForItemAtIndexPath) {
|
||||||
return [collectionView.asyncDelegate collectionNode:collectionView.collectionNode constrainedSizeForItemAtIndexPath:indexPath];
|
result = [collectionView.asyncDelegate collectionNode:collectionView.collectionNode constrainedSizeForItemAtIndexPath:indexPath];
|
||||||
} else if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated) {
|
} else if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated) {
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
result = [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
} else {
|
} else {
|
||||||
// With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source
|
// With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source
|
||||||
ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDelegate.");
|
ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDelegate.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CGSize itemSize = _layout.itemSize;
|
// If we got no size range:
|
||||||
if (CGSizeEqualToSize(itemSize, kDefaultItemSize) == NO) {
|
if (ASSizeRangeEqualToSizeRange(result, ASSizeRangeUnconstrained)) {
|
||||||
return ASSizeRangeMake(itemSize, itemSize);
|
// Use itemSize if they set it.
|
||||||
|
CGSize itemSize = _layout.itemSize;
|
||||||
|
if (CGSizeEqualToSize(itemSize, kDefaultItemSize) == NO) {
|
||||||
|
result = ASSizeRangeMake(itemSize, itemSize);
|
||||||
|
} else {
|
||||||
|
// Compute constraint from scroll direction otherwise.
|
||||||
|
result = NodeConstrainedSizeForScrollDirection(collectionView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NodeConstrainedSizeForScrollDirection(collectionView);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#import "ASCollectionView.h"
|
#import "ASCollectionView.h"
|
||||||
#import "ASCollectionView+Undeprecated.h"
|
#import "ASCollectionView+Undeprecated.h"
|
||||||
|
#import "ASCollectionInternal.h"
|
||||||
|
|
||||||
#pragma mark - Helper Functions
|
#pragma mark - Helper Functions
|
||||||
|
|
||||||
|
|||||||
@@ -719,6 +719,8 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat
|
|||||||
[_nodeContexts[ASDataControllerRowNodeKind] removeObjectsAtIndexes:sections];
|
[_nodeContexts[ASDataControllerRowNodeKind] removeObjectsAtIndexes:sections];
|
||||||
|
|
||||||
dispatch_group_wait(_editingTransactionGroup, DISPATCH_TIME_FOREVER);
|
dispatch_group_wait(_editingTransactionGroup, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
[self prepareForDeleteSections:sections];
|
||||||
dispatch_group_async(_editingTransactionGroup, _editingTransactionQueue, ^{
|
dispatch_group_async(_editingTransactionGroup, _editingTransactionQueue, ^{
|
||||||
[self willDeleteSections:sections];
|
[self willDeleteSections:sections];
|
||||||
|
|
||||||
@@ -745,6 +747,11 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat
|
|||||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)prepareForDeleteSections:(NSIndexSet *)sections
|
||||||
|
{
|
||||||
|
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||||
|
}
|
||||||
|
|
||||||
- (void)willInsertSections:(NSIndexSet *)sections
|
- (void)willInsertSections:(NSIndexSet *)sections
|
||||||
{
|
{
|
||||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||||
|
|||||||
@@ -22,4 +22,7 @@
|
|||||||
|
|
||||||
- (NSString *)as_smallDescription;
|
- (NSString *)as_smallDescription;
|
||||||
|
|
||||||
|
/// Returns all the section indexes contained in the index paths array.
|
||||||
|
+ (NSIndexSet *)as_sectionsFromIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -77,4 +77,13 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSIndexSet *)as_sectionsFromIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||||
|
{
|
||||||
|
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||||
|
for (NSIndexPath *indexPath in indexPaths) {
|
||||||
|
[result addIndex:indexPath.section];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
17
AsyncDisplayKit/Details/_ASCollectionViewCell.h
Normal file
17
AsyncDisplayKit/Details/_ASCollectionViewCell.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// _ASCollectionViewCell.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/30/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@class ASCellNode;
|
||||||
|
|
||||||
|
@interface _ASCollectionViewCell : UICollectionViewCell
|
||||||
|
@property (nonatomic, weak) ASCellNode *node;
|
||||||
|
@property (nonatomic, strong) UICollectionViewLayoutAttributes *layoutAttributes;
|
||||||
|
@end
|
||||||
|
|
||||||
74
AsyncDisplayKit/Details/_ASCollectionViewCell.m
Normal file
74
AsyncDisplayKit/Details/_ASCollectionViewCell.m
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// _ASCollectionViewCell.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/30/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "_ASCollectionViewCell.h"
|
||||||
|
#import "ASCellNode+Internal.h"
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@implementation _ASCollectionViewCell
|
||||||
|
|
||||||
|
- (void)setNode:(ASCellNode *)node
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
node.layoutAttributes = _layoutAttributes;
|
||||||
|
_node = node;
|
||||||
|
self.backgroundColor = node.backgroundColor;
|
||||||
|
self.clipsToBounds = node.clipsToBounds;
|
||||||
|
[node __setSelectedFromUIKit:self.selected];
|
||||||
|
[node __setHighlightedFromUIKit:self.highlighted];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSelected:(BOOL)selected
|
||||||
|
{
|
||||||
|
[super setSelected:selected];
|
||||||
|
[_node __setSelectedFromUIKit:selected];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setHighlighted:(BOOL)highlighted
|
||||||
|
{
|
||||||
|
[super setHighlighted:highlighted];
|
||||||
|
[_node __setHighlightedFromUIKit:highlighted];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
||||||
|
{
|
||||||
|
_layoutAttributes = layoutAttributes;
|
||||||
|
_node.layoutAttributes = layoutAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)prepareForReuse
|
||||||
|
{
|
||||||
|
self.layoutAttributes = nil;
|
||||||
|
|
||||||
|
// Need to clear node pointer before UIKit calls setSelected:NO / setHighlighted:NO on its cells
|
||||||
|
self.node = nil;
|
||||||
|
[super prepareForReuse];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In the initial case, this is called by UICollectionView during cell dequeueing, before
|
||||||
|
* we get a chance to assign a node to it, so we must be sure to set these layout attributes
|
||||||
|
* on our node when one is next assigned to us in @c setNode: . Since there may be cases when we _do_ already
|
||||||
|
* have our node assigned e.g. during a layout update for existing cells, we also attempt
|
||||||
|
* to update it now.
|
||||||
|
*/
|
||||||
|
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
||||||
|
{
|
||||||
|
self.layoutAttributes = layoutAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep our node filling our content view.
|
||||||
|
*/
|
||||||
|
- (void)layoutSubviews
|
||||||
|
{
|
||||||
|
[super layoutSubviews];
|
||||||
|
self.node.frame = self.contentView.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
34
AsyncDisplayKit/IGListAdapter+AsyncDisplayKit.h
Normal file
34
AsyncDisplayKit/IGListAdapter+AsyncDisplayKit.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// IGListAdapter+AsyncDisplayKit.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class ASCollectionNode;
|
||||||
|
|
||||||
|
@interface IGListAdapter (AsyncDisplayKit)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect this list adapter to the given collection node.
|
||||||
|
*
|
||||||
|
* @param collectionNode The collection node to drive with this list adapter.
|
||||||
|
*
|
||||||
|
* @note This method may only be called once per list adapter,
|
||||||
|
* and it must be called on the main thread. -[UIViewController init]
|
||||||
|
* is a good place to call it. This method does not retain the collection node.
|
||||||
|
*/
|
||||||
|
- (void)setASDKCollectionNode:(ASCollectionNode *)collectionNode;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif // IG_LIST_KIT
|
||||||
45
AsyncDisplayKit/IGListAdapter+AsyncDisplayKit.m
Normal file
45
AsyncDisplayKit/IGListAdapter+AsyncDisplayKit.m
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// IGListAdapter+AsyncDisplayKit.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
|
||||||
|
#import "IGListAdapter+AsyncDisplayKit.h"
|
||||||
|
#import "ASIGListAdapterBasedDataSource.h"
|
||||||
|
#import "ASAssert.h"
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
@implementation IGListAdapter (AsyncDisplayKit)
|
||||||
|
|
||||||
|
- (void)setASDKCollectionNode:(ASCollectionNode *)collectionNode
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
|
// Attempt to retrieve previous data source.
|
||||||
|
ASIGListAdapterBasedDataSource *dataSource = objc_getAssociatedObject(self, _cmd);
|
||||||
|
// Bomb if we already made one.
|
||||||
|
if (dataSource != nil) {
|
||||||
|
ASDisplayNodeFailAssert(@"Attempt to call %@ multiple times on the same list adapter. Not currently allowed!", NSStringFromSelector(_cmd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a data source and retain it.
|
||||||
|
dataSource = [[ASIGListAdapterBasedDataSource alloc] initWithListAdapter:self];
|
||||||
|
objc_setAssociatedObject(self, _cmd, dataSource, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
|
||||||
|
// Attach the data source to the collection node.
|
||||||
|
collectionNode.dataSource = dataSource;
|
||||||
|
collectionNode.delegate = dataSource;
|
||||||
|
__weak IGListAdapter *weakSelf = self;
|
||||||
|
[collectionNode onDidLoad:^(__kindof ASCollectionNode * _Nonnull collectionNode) {
|
||||||
|
weakSelf.collectionView = collectionNode.view;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif // IG_LIST_KIT
|
||||||
34
AsyncDisplayKit/Private/ASCollectionInteropProtocols.h
Normal file
34
AsyncDisplayKit/Private/ASCollectionInteropProtocols.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// ASCollectionDataSourceInterop.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/20/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocols that allow the data source/delegate extra hooks,
|
||||||
|
* to facilitate interop e.g. with IGListKit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@protocol ASCollectionDataSourceInterop <ASCollectionDataSource>
|
||||||
|
|
||||||
|
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@protocol ASCollectionDelegateInterop <ASCollectionDelegate>
|
||||||
|
|
||||||
|
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@@ -113,6 +113,17 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCellNode *> *nodes, NS
|
|||||||
*/
|
*/
|
||||||
- (void)willInsertSections:(NSIndexSet *)sections;
|
- (void)willInsertSections:(NSIndexSet *)sections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the subclass to perform setup before sections are deleted in the data controller
|
||||||
|
*
|
||||||
|
* @discussion This method will be performed before the data controller enters its editing queue.
|
||||||
|
* The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||||
|
* data stores before entering into editing the backing store on a background thread.
|
||||||
|
*
|
||||||
|
* @param sections Indices of sections to be inserted
|
||||||
|
*/
|
||||||
|
- (void)prepareForDeleteSections:(NSIndexSet *)sections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the subclass that the data controller will delete sections at the given positions
|
* Notifies the subclass that the data controller will delete sections at the given positions
|
||||||
*
|
*
|
||||||
@@ -124,18 +135,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCellNode *> *nodes, NS
|
|||||||
*/
|
*/
|
||||||
- (void)willDeleteSections:(NSIndexSet *)sections;
|
- (void)willDeleteSections:(NSIndexSet *)sections;
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the subclass that the data controller will move a section to a new position
|
|
||||||
*
|
|
||||||
* @discussion This method will be performed on the data controller's editing background queue before the parent's
|
|
||||||
* concrete implementation. This is a great place to perform any additional transformations like supplementary views
|
|
||||||
* or header/footer nodes.
|
|
||||||
*
|
|
||||||
* @param section Index of current section position
|
|
||||||
* @param newSection Index of new section position
|
|
||||||
*/
|
|
||||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the subclass to perform setup before rows are inserted in the data controller.
|
* Notifies the subclass to perform setup before rows are inserted in the data controller.
|
||||||
*
|
*
|
||||||
|
|||||||
22
AsyncDisplayKit/Private/ASIGListAdapterBasedDataSource.h
Normal file
22
AsyncDisplayKit/Private/ASIGListAdapterBasedDataSource.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// ASIGListAdapterBasedDataSource.h
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
#import "ASCollectionInteropProtocols.h"
|
||||||
|
|
||||||
|
AS_SUBCLASSING_RESTRICTED
|
||||||
|
@interface ASIGListAdapterBasedDataSource : NSObject <ASCollectionDataSourceInterop, ASCollectionDelegateInterop, ASCollectionDelegateFlowLayout>
|
||||||
|
|
||||||
|
- (instancetype)initWithListAdapter:(IGListAdapter *)listAdapter;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
315
AsyncDisplayKit/Private/ASIGListAdapterBasedDataSource.m
Normal file
315
AsyncDisplayKit/Private/ASIGListAdapterBasedDataSource.m
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
//
|
||||||
|
// ASIGListAdapterBasedDataSource.m
|
||||||
|
// AsyncDisplayKit
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/19/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if IG_LIST_KIT
|
||||||
|
|
||||||
|
#import "ASIGListAdapterBasedDataSource.h"
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
typedef IGListSectionController<IGListSectionType, ASSectionController> ASIGSectionController;
|
||||||
|
|
||||||
|
/// The optional methods that a class implements from ASSectionController.
|
||||||
|
/// Note: Bitfields are not supported by NSValue so we can't use them.
|
||||||
|
typedef struct {
|
||||||
|
BOOL sizeRangeForItem;
|
||||||
|
BOOL shouldBatchFetch;
|
||||||
|
BOOL beginBatchFetchWithContext;
|
||||||
|
} ASSectionControllerOverrides;
|
||||||
|
|
||||||
|
/// The optional methods that a class implements from ASSupplementaryNodeSource.
|
||||||
|
/// Note: Bitfields are not supported by NSValue so we can't use them.
|
||||||
|
typedef struct {
|
||||||
|
BOOL sizeRangeForSupplementary;
|
||||||
|
} ASSupplementarySourceOverrides;
|
||||||
|
|
||||||
|
@protocol ASIGSupplementaryNodeSource <IGListSupplementaryViewSource, ASSupplementaryNodeSource>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ASIGListAdapterBasedDataSource ()
|
||||||
|
@property (nonatomic, weak, readonly) IGListAdapter *listAdapter;
|
||||||
|
@property (nonatomic, readonly) id<UICollectionViewDelegateFlowLayout> delegate;
|
||||||
|
@property (nonatomic, readonly) id<UICollectionViewDataSource> dataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The section controller that we will forward beginBatchFetchWithContext: to.
|
||||||
|
* Since shouldBatchFetch: is called on main, we capture the last section controller in there,
|
||||||
|
* and then we use it and clear it in beginBatchFetchWithContext: (on default queue).
|
||||||
|
*
|
||||||
|
* It is safe to use it without a lock in this limited way, since those two methods will
|
||||||
|
* never execute in parallel.6
|
||||||
|
*/
|
||||||
|
@property (nonatomic, weak) ASIGSectionController *sectionControllerForBatchFetching;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASIGListAdapterBasedDataSource
|
||||||
|
|
||||||
|
- (instancetype)initWithListAdapter:(IGListAdapter *)listAdapter
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
[ASIGListAdapterBasedDataSource setASCollectionViewSuperclass];
|
||||||
|
[ASIGListAdapterBasedDataSource configureUpdater:listAdapter.updater];
|
||||||
|
|
||||||
|
ASDisplayNodeAssert([listAdapter conformsToProtocol:@protocol(UICollectionViewDataSource)], @"Expected IGListAdapter to conform to UICollectionViewDataSource.");
|
||||||
|
ASDisplayNodeAssert([listAdapter conformsToProtocol:@protocol(UICollectionViewDelegateFlowLayout)], @"Expected IGListAdapter to conform to UICollectionViewDelegateFlowLayout.");
|
||||||
|
_listAdapter = listAdapter;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<UICollectionViewDataSource>)dataSource
|
||||||
|
{
|
||||||
|
return (id<UICollectionViewDataSource>)_listAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<UICollectionViewDelegateFlowLayout>)delegate
|
||||||
|
{
|
||||||
|
return (id<UICollectionViewDelegateFlowLayout>)_listAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASCollectionDelegate
|
||||||
|
|
||||||
|
- (void)collectionNode:(ASCollectionNode *)collectionNode didSelectItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
[self.delegate collectionView:collectionNode.view didSelectItemAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||||
|
{
|
||||||
|
[self.delegate scrollViewDidScroll:scrollView];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
||||||
|
{
|
||||||
|
[self.delegate scrollViewWillBeginDragging:scrollView];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
|
||||||
|
{
|
||||||
|
[self.delegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldBatchFetchForCollectionNode:(ASCollectionNode *)collectionNode
|
||||||
|
{
|
||||||
|
NSInteger sectionCount = [self numberOfSectionsInCollectionNode:collectionNode];
|
||||||
|
if (sectionCount == 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they implement shouldBatchFetch, call it. Otherwise, just say YES if they implement beginBatchFetch.
|
||||||
|
ASIGSectionController *ctrl = [self sectionControllerForSection:sectionCount - 1];
|
||||||
|
ASSectionControllerOverrides o = [ASIGListAdapterBasedDataSource overridesForSectionControllerClass:ctrl.class];
|
||||||
|
BOOL result = (o.shouldBatchFetch ? [ctrl shouldBatchFetch] : o.beginBatchFetchWithContext);
|
||||||
|
if (result) {
|
||||||
|
self.sectionControllerForBatchFetching = ctrl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)collectionNode:(ASCollectionNode *)collectionNode willBeginBatchFetchWithContext:(ASBatchContext *)context
|
||||||
|
{
|
||||||
|
ASIGSectionController *ctrl = self.sectionControllerForBatchFetching;
|
||||||
|
self.sectionControllerForBatchFetching = nil;
|
||||||
|
[ctrl beginBatchFetchWithContext:context];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: It is not documented that ASCollectionNode will forward these UIKit delegate calls if they are implemented.
|
||||||
|
* It is not considered harmful to do so, and adding them to documentation will confuse most users, who should
|
||||||
|
* instead using the ASCollectionDelegate callbacks.
|
||||||
|
*/
|
||||||
|
#pragma mark - ASCollectionDelegateInterop
|
||||||
|
|
||||||
|
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
[self.delegate collectionView:collectionView willDisplayCell:cell forItemAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
[self.delegate collectionView:collectionView didEndDisplayingCell:cell forItemAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASCollectionDelegateFlowLayout
|
||||||
|
|
||||||
|
- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode sizeRangeForHeaderInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
id<ASIGSupplementaryNodeSource> src = [self supplementaryElementSourceForSection:section];
|
||||||
|
if ([ASIGListAdapterBasedDataSource overridesForSupplementarySourceClass:[src class]].sizeRangeForSupplementary) {
|
||||||
|
return [src sizeRangeForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndex:0];
|
||||||
|
} else {
|
||||||
|
return ASSizeRangeZero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode sizeRangeForFooterInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
id<ASIGSupplementaryNodeSource> src = [self supplementaryElementSourceForSection:section];
|
||||||
|
if ([ASIGListAdapterBasedDataSource overridesForSupplementarySourceClass:[src class]].sizeRangeForSupplementary) {
|
||||||
|
return [src sizeRangeForSupplementaryElementOfKind:UICollectionElementKindSectionFooter atIndex:0];
|
||||||
|
} else {
|
||||||
|
return ASSizeRangeZero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
|
||||||
|
{
|
||||||
|
return [self.delegate collectionView:collectionView layout:collectionViewLayout insetForSectionAtIndex:section];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
|
||||||
|
{
|
||||||
|
return [self.delegate collectionView:collectionView layout:collectionViewLayout minimumLineSpacingForSectionAtIndex:section];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
|
||||||
|
{
|
||||||
|
return [self.delegate collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASCollectionDataSource
|
||||||
|
|
||||||
|
- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
return [self.dataSource collectionView:collectionNode.view numberOfItemsInSection:section];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)numberOfSectionsInCollectionNode:(ASCollectionNode *)collectionNode
|
||||||
|
{
|
||||||
|
return [self.dataSource numberOfSectionsInCollectionView:collectionNode.view];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [[self sectionControllerForSection:indexPath.section] nodeBlockForItemAtIndex:indexPath.item];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
ASIGSectionController *ctrl = [self sectionControllerForSection:indexPath.section];
|
||||||
|
if ([ASIGListAdapterBasedDataSource overridesForSectionControllerClass:ctrl.class].sizeRangeForItem) {
|
||||||
|
return [ctrl sizeRangeForItemAtIndex:indexPath.item];
|
||||||
|
} else {
|
||||||
|
return ASSizeRangeUnconstrained;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASCellNode *)collectionNode:(ASCollectionNode *)collectionNode nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [[self supplementaryElementSourceForSection:indexPath.section] nodeForSupplementaryElementOfKind:kind atIndex:indexPath.item];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)collectionNode:(ASCollectionNode *)collectionNode supplementaryElementKindsInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
return [[self supplementaryElementSourceForSection:section] supportedElementKinds];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASCollectionDataSourceInterop
|
||||||
|
|
||||||
|
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [self.dataSource collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [self.dataSource collectionView:collectionView viewForSupplementaryElementOfKind:kind atIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helpers
|
||||||
|
|
||||||
|
- (id<ASIGSupplementaryNodeSource>)supplementaryElementSourceForSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
ASIGSectionController *ctrl = [self sectionControllerForSection:section];
|
||||||
|
id<ASIGSupplementaryNodeSource> src = (id<ASIGSupplementaryNodeSource>)ctrl.supplementaryViewSource;
|
||||||
|
ASDisplayNodeAssert(src == nil || [src conformsToProtocol:@protocol(ASSupplementaryNodeSource)], @"Supplementary view source should conform to %@", NSStringFromProtocol(@protocol(ASSupplementaryNodeSource)));
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASIGSectionController *)sectionControllerForSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
id object = [_listAdapter objectAtSection:section];
|
||||||
|
ASIGSectionController *ctrl = (ASIGSectionController *)[_listAdapter sectionControllerForObject:object];
|
||||||
|
ASDisplayNodeAssert([ctrl conformsToProtocol:@protocol(ASSectionController)], @"Expected section controller to conform to %@. Controller: %@", NSStringFromProtocol(@protocol(ASSectionController)), ctrl);
|
||||||
|
return ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ASCollectionView's superclass to IGListCollectionView.
|
||||||
|
* Scary! If IGListKit removed the subclassing restriction, we could
|
||||||
|
* use #if in the @interface to choose the superclass based on
|
||||||
|
* whether we have IGListKit available.
|
||||||
|
*/
|
||||||
|
+ (void)setASCollectionViewSuperclass
|
||||||
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
class_setSuperclass([ASCollectionView class], [IGListCollectionView class]);
|
||||||
|
});
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensure updater won't call reloadData on us.
|
||||||
|
+ (void)configureUpdater:(id<IGListUpdatingDelegate>)updater
|
||||||
|
{
|
||||||
|
// Cast to NSObject will be removed after https://github.com/Instagram/IGListKit/pull/435
|
||||||
|
if ([(id<NSObject>)updater isKindOfClass:[IGListAdapterUpdater class]]) {
|
||||||
|
[(IGListAdapterUpdater *)updater setAllowsBackgroundReloading:NO];
|
||||||
|
} else {
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSLog(@"WARNING: Use of non-%@ updater with AsyncDisplayKit is discouraged. Updater: %@", NSStringFromClass([IGListAdapterUpdater class]), updater);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (ASSupplementarySourceOverrides)overridesForSupplementarySourceClass:(Class)c
|
||||||
|
{
|
||||||
|
static NSCache<Class, NSValue *> *cache;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
cache = [[NSCache alloc] init];
|
||||||
|
});
|
||||||
|
NSValue *obj = [cache objectForKey:c];
|
||||||
|
ASSupplementarySourceOverrides o;
|
||||||
|
if (obj == nil) {
|
||||||
|
o.sizeRangeForSupplementary = [c instancesRespondToSelector:@selector(sizeRangeForSupplementaryElementOfKind:atIndex:)];
|
||||||
|
obj = [NSValue valueWithBytes:&o objCType:@encode(ASSupplementarySourceOverrides)];
|
||||||
|
[cache setObject:obj forKey:c];
|
||||||
|
} else {
|
||||||
|
[obj getValue:&o];
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (ASSectionControllerOverrides)overridesForSectionControllerClass:(Class)c
|
||||||
|
{
|
||||||
|
static NSCache<Class, NSValue *> *cache;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
cache = [[NSCache alloc] init];
|
||||||
|
});
|
||||||
|
NSValue *obj = [cache objectForKey:c];
|
||||||
|
ASSectionControllerOverrides o;
|
||||||
|
if (obj == nil) {
|
||||||
|
o.sizeRangeForItem = [c instancesRespondToSelector:@selector(sizeRangeForItemAtIndex:)];
|
||||||
|
o.beginBatchFetchWithContext = [c instancesRespondToSelector:@selector(beginBatchFetchWithContext:)];
|
||||||
|
o.shouldBatchFetch = [c instancesRespondToSelector:@selector(shouldBatchFetch)];
|
||||||
|
obj = [NSValue valueWithBytes:&o objCType:@encode(ASSectionControllerOverrides)];
|
||||||
|
[cache setObject:obj forKey:c];
|
||||||
|
} else {
|
||||||
|
[obj getValue:&o];
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif // IG_LIST_KIT
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
|
|
||||||
@interface ASCollectionView (InternalTesting)
|
@interface ASCollectionView (InternalTesting)
|
||||||
|
|
||||||
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController;
|
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController sections:(nonnull NSIndexSet *)sections;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||||
[collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader];
|
[collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader];
|
||||||
XCTAssertEqualObjects([collectionView supplementaryNodeKindsInDataController:nil], @[UICollectionElementKindSectionHeader]);
|
XCTAssertEqualObjects([collectionView supplementaryNodeKindsInDataController:nil sections:[NSIndexSet indexSetWithIndex:0]], @[UICollectionElementKindSectionHeader]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testReloadIfNeeded
|
- (void)testReloadIfNeeded
|
||||||
|
|||||||
@@ -2144,11 +2144,16 @@ static bool stringContainsPointer(NSString *description, id p) {
|
|||||||
XCTAssertNoThrow([node.view layoutIfNeeded]);
|
XCTAssertNoThrow([node.view layoutIfNeeded]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatOnDidLoadThrowsIfCalledOnLoaded
|
- (void)testThatOnDidLoadThrowsIfCalledOnLoadedOffMain
|
||||||
{
|
{
|
||||||
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||||
[node view];
|
[node view];
|
||||||
XCTAssertThrows([node onDidLoad:^(ASDisplayNode * _Nonnull node) { }]);
|
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
||||||
|
[NSThread detachNewThreadWithBlock:^{
|
||||||
|
XCTAssertThrows([node onDidLoad:^(ASDisplayNode * _Nonnull node) { }]);
|
||||||
|
dispatch_semaphore_signal(sem);
|
||||||
|
}];
|
||||||
|
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatOnDidLoadWorks
|
- (void)testThatOnDidLoadWorks
|
||||||
|
|||||||
15
build.sh
15
build.sh
@@ -30,7 +30,20 @@ if [ "$MODE" = "tests" ]; then
|
|||||||
-scheme AsyncDisplayKit \
|
-scheme AsyncDisplayKit \
|
||||||
-sdk "$SDK" \
|
-sdk "$SDK" \
|
||||||
-destination "$PLATFORM" \
|
-destination "$PLATFORM" \
|
||||||
build test | xcpretty $FORMATTER
|
build-for-testing test | xcpretty $FORMATTER
|
||||||
|
trap - EXIT
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$MODE" = "tests_listkit" ]; then
|
||||||
|
echo "Building & testing AsyncDisplayKit+IGListKit."
|
||||||
|
pod install --project-directory=ASDKListKit
|
||||||
|
set -o pipefail && xcodebuild \
|
||||||
|
-workspace ASDKListKit/ASDKListKit.xcworkspace \
|
||||||
|
-scheme ASDKListKitTests \
|
||||||
|
-sdk "$SDK" \
|
||||||
|
-destination "$PLATFORM" \
|
||||||
|
build-for-testing test | xcpretty $FORMATTER
|
||||||
trap - EXIT
|
trap - EXIT
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#import "SupplementaryNode.h"
|
#import "SupplementaryNode.h"
|
||||||
#import "ItemNode.h"
|
#import "ItemNode.h"
|
||||||
|
|
||||||
@interface ViewController () <ASCollectionDataSource, ASCollectionViewDelegateFlowLayout>
|
@interface ViewController () <ASCollectionDataSource, ASCollectionDelegateFlowLayout>
|
||||||
|
|
||||||
@property (nonatomic, strong) ASCollectionNode *collectionNode;
|
@property (nonatomic, strong) ASCollectionNode *collectionNode;
|
||||||
@property (nonatomic, strong) NSArray *data;
|
@property (nonatomic, strong) NSArray *data;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
source 'https://github.com/CocoaPods/Specs.git'
|
source 'https://github.com/CocoaPods/Specs.git'
|
||||||
platform :ios, '7.0'
|
platform :ios, '8.0'
|
||||||
target 'Sample' do
|
target 'Sample' do
|
||||||
pod 'AsyncDisplayKit', :path => '../..'
|
pod 'AsyncDisplayKit/IGListKit', :path => '../..'
|
||||||
|
pod 'AsyncDisplayKit/PINRemoteImage', :path => '../..'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,11 @@
|
|||||||
768843931CAA37EF00D8629E /* UserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437B1CAA37EF00D8629E /* UserModel.m */; };
|
768843931CAA37EF00D8629E /* UserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437B1CAA37EF00D8629E /* UserModel.m */; };
|
||||||
768843961CAA37EF00D8629E /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437E1CAA37EF00D8629E /* Utilities.m */; };
|
768843961CAA37EF00D8629E /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437E1CAA37EF00D8629E /* Utilities.m */; };
|
||||||
B13424EE6D36C2EC5D1030B6 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */; };
|
B13424EE6D36C2EC5D1030B6 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */; };
|
||||||
|
CC00D1571E15912F004E5502 /* PhotoFeedListKitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC00D1561E15912F004E5502 /* PhotoFeedListKitViewController.m */; };
|
||||||
|
CC5369AC1E15925200FAD348 /* PhotoFeedSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5369AB1E15925200FAD348 /* PhotoFeedSectionController.m */; };
|
||||||
|
CC5532171E15CC1E0011C01F /* ASCollectionSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532161E15CC1E0011C01F /* ASCollectionSectionController.m */; };
|
||||||
|
CC6350BB1E1C482D002BC613 /* TailLoadingNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6350BA1E1C482D002BC613 /* TailLoadingNode.m */; };
|
||||||
|
CC85250F1E36B392008EABE6 /* FeedHeaderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC85250E1E36B392008EABE6 /* FeedHeaderNode.m */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@@ -80,6 +85,17 @@
|
|||||||
7688437F1CAA37EF00D8629E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
7688437F1CAA37EF00D8629E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
97A9B1BAF4265967672F9EA3 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; };
|
97A9B1BAF4265967672F9EA3 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
CC00D1551E15912F004E5502 /* PhotoFeedListKitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoFeedListKitViewController.h; sourceTree = "<group>"; };
|
||||||
|
CC00D1561E15912F004E5502 /* PhotoFeedListKitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoFeedListKitViewController.m; sourceTree = "<group>"; };
|
||||||
|
CC5369AA1E15925200FAD348 /* PhotoFeedSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoFeedSectionController.h; sourceTree = "<group>"; };
|
||||||
|
CC5369AB1E15925200FAD348 /* PhotoFeedSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoFeedSectionController.m; sourceTree = "<group>"; };
|
||||||
|
CC5532111E159D770011C01F /* RefreshingSectionControllerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefreshingSectionControllerType.h; sourceTree = "<group>"; };
|
||||||
|
CC5532151E15CC1E0011C01F /* ASCollectionSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionSectionController.h; sourceTree = "<group>"; };
|
||||||
|
CC5532161E15CC1E0011C01F /* ASCollectionSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionSectionController.m; sourceTree = "<group>"; };
|
||||||
|
CC6350B91E1C482D002BC613 /* TailLoadingNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TailLoadingNode.h; sourceTree = "<group>"; };
|
||||||
|
CC6350BA1E1C482D002BC613 /* TailLoadingNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TailLoadingNode.m; sourceTree = "<group>"; };
|
||||||
|
CC85250D1E36B392008EABE6 /* FeedHeaderNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FeedHeaderNode.h; sourceTree = "<group>"; };
|
||||||
|
CC85250E1E36B392008EABE6 /* FeedHeaderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FeedHeaderNode.m; sourceTree = "<group>"; };
|
||||||
D09B5DF0BFB37583DE8F3142 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = "<group>"; };
|
D09B5DF0BFB37583DE8F3142 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -169,6 +185,7 @@
|
|||||||
children = (
|
children = (
|
||||||
767A5F161CAA3D96004CDA8D /* UIKit */,
|
767A5F161CAA3D96004CDA8D /* UIKit */,
|
||||||
767A5F151CAA3D90004CDA8D /* ASDK */,
|
767A5F151CAA3D90004CDA8D /* ASDK */,
|
||||||
|
CC00D1581E159132004E5502 /* ASDK-ListKit */,
|
||||||
);
|
);
|
||||||
name = Controller;
|
name = Controller;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -239,6 +256,10 @@
|
|||||||
767A5F1A1CAA3DBF004CDA8D /* ASDK */ = {
|
767A5F1A1CAA3DBF004CDA8D /* ASDK */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CC85250D1E36B392008EABE6 /* FeedHeaderNode.h */,
|
||||||
|
CC85250E1E36B392008EABE6 /* FeedHeaderNode.m */,
|
||||||
|
CC6350B91E1C482D002BC613 /* TailLoadingNode.h */,
|
||||||
|
CC6350BA1E1C482D002BC613 /* TailLoadingNode.m */,
|
||||||
7688435B1CAA37EF00D8629E /* PhotoCellNode.h */,
|
7688435B1CAA37EF00D8629E /* PhotoCellNode.h */,
|
||||||
768843731CAA37EF00D8629E /* PhotoCellNode.m */,
|
768843731CAA37EF00D8629E /* PhotoCellNode.m */,
|
||||||
768843541CAA37EF00D8629E /* CommentsNode.h */,
|
768843541CAA37EF00D8629E /* CommentsNode.h */,
|
||||||
@@ -247,6 +268,20 @@
|
|||||||
name = ASDK;
|
name = ASDK;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
CC00D1581E159132004E5502 /* ASDK-ListKit */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CC5532111E159D770011C01F /* RefreshingSectionControllerType.h */,
|
||||||
|
CC00D1551E15912F004E5502 /* PhotoFeedListKitViewController.h */,
|
||||||
|
CC00D1561E15912F004E5502 /* PhotoFeedListKitViewController.m */,
|
||||||
|
CC5369AA1E15925200FAD348 /* PhotoFeedSectionController.h */,
|
||||||
|
CC5369AB1E15925200FAD348 /* PhotoFeedSectionController.m */,
|
||||||
|
CC5532151E15CC1E0011C01F /* ASCollectionSectionController.h */,
|
||||||
|
CC5532161E15CC1E0011C01F /* ASCollectionSectionController.m */,
|
||||||
|
);
|
||||||
|
name = "ASDK-ListKit";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -378,15 +413,20 @@
|
|||||||
768843831CAA37EF00D8629E /* CommentsNode.m in Sources */,
|
768843831CAA37EF00D8629E /* CommentsNode.m in Sources */,
|
||||||
768843961CAA37EF00D8629E /* Utilities.m in Sources */,
|
768843961CAA37EF00D8629E /* Utilities.m in Sources */,
|
||||||
768843931CAA37EF00D8629E /* UserModel.m in Sources */,
|
768843931CAA37EF00D8629E /* UserModel.m in Sources */,
|
||||||
|
CC5532171E15CC1E0011C01F /* ASCollectionSectionController.m in Sources */,
|
||||||
768843801CAA37EF00D8629E /* AppDelegate.m in Sources */,
|
768843801CAA37EF00D8629E /* AppDelegate.m in Sources */,
|
||||||
768843811CAA37EF00D8629E /* CommentFeedModel.m in Sources */,
|
768843811CAA37EF00D8629E /* CommentFeedModel.m in Sources */,
|
||||||
7688438E1CAA37EF00D8629E /* PhotoFeedNodeController.m in Sources */,
|
7688438E1CAA37EF00D8629E /* PhotoFeedNodeController.m in Sources */,
|
||||||
|
CC6350BB1E1C482D002BC613 /* TailLoadingNode.m in Sources */,
|
||||||
|
CC85250F1E36B392008EABE6 /* FeedHeaderNode.m in Sources */,
|
||||||
768843841CAA37EF00D8629E /* CommentView.m in Sources */,
|
768843841CAA37EF00D8629E /* CommentView.m in Sources */,
|
||||||
768843881CAA37EF00D8629E /* LocationModel.m in Sources */,
|
768843881CAA37EF00D8629E /* LocationModel.m in Sources */,
|
||||||
768843901CAA37EF00D8629E /* PhotoModel.m in Sources */,
|
768843901CAA37EF00D8629E /* PhotoModel.m in Sources */,
|
||||||
768843911CAA37EF00D8629E /* PhotoTableViewCell.m in Sources */,
|
768843911CAA37EF00D8629E /* PhotoTableViewCell.m in Sources */,
|
||||||
|
CC00D1571E15912F004E5502 /* PhotoFeedListKitViewController.m in Sources */,
|
||||||
7688438B1CAA37EF00D8629E /* PhotoCellNode.m in Sources */,
|
7688438B1CAA37EF00D8629E /* PhotoCellNode.m in Sources */,
|
||||||
7688438D1CAA37EF00D8629E /* PhotoFeedModel.m in Sources */,
|
7688438D1CAA37EF00D8629E /* PhotoFeedModel.m in Sources */,
|
||||||
|
CC5369AC1E15925200FAD348 /* PhotoFeedSectionController.m in Sources */,
|
||||||
768843851CAA37EF00D8629E /* ImageURLModel.m in Sources */,
|
768843851CAA37EF00D8629E /* ImageURLModel.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
10
examples/ASDKgram/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/ASDKgram/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Sample.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
28
examples/ASDKgram/Sample/ASCollectionSectionController.h
Normal file
28
examples/ASDKgram/Sample/ASCollectionSectionController.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// ASCollectionSectionController.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface ASCollectionSectionController : IGListSectionController
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The items managed by this section controller.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, strong, readonly) NSArray<id<IGListDiffable>> *items;
|
||||||
|
|
||||||
|
- (void)setItems:(NSArray<id<IGListDiffable>> *)newItems
|
||||||
|
animated:(BOOL)animated
|
||||||
|
completion:(nullable void(^)())completion;
|
||||||
|
|
||||||
|
- (NSInteger)numberOfItems;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
79
examples/ASDKgram/Sample/ASCollectionSectionController.m
Normal file
79
examples/ASDKgram/Sample/ASCollectionSectionController.m
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// ASCollectionSectionController.m
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASCollectionSectionController.h"
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface ASCollectionSectionController ()
|
||||||
|
@property (nonatomic, strong, readonly) dispatch_queue_t diffingQueue;
|
||||||
|
|
||||||
|
/// The items that have been diffed and are waiting to be submitted to the collection view.
|
||||||
|
/// Should always be accessed on the diffing queue, and should never be accessed
|
||||||
|
/// before the initial items are read (in -numberOfItems).
|
||||||
|
@property (nonatomic, copy) NSArray *pendingItems;
|
||||||
|
|
||||||
|
@property (nonatomic) BOOL initialItemsRead;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASCollectionSectionController
|
||||||
|
@synthesize diffingQueue = _diffingQueue;
|
||||||
|
|
||||||
|
- (NSInteger)numberOfItems
|
||||||
|
{
|
||||||
|
if (_initialItemsRead == NO) {
|
||||||
|
_pendingItems = self.items;
|
||||||
|
_initialItemsRead = YES;
|
||||||
|
}
|
||||||
|
return self.items.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (dispatch_queue_t)diffingQueue
|
||||||
|
{
|
||||||
|
if (_diffingQueue == nil) {
|
||||||
|
_diffingQueue = dispatch_queue_create("ASCollectionSectionController.diffingQueue", DISPATCH_QUEUE_SERIAL);
|
||||||
|
}
|
||||||
|
return _diffingQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setItems:(NSArray *)newItems animated:(BOOL)animated completion:(void(^)())completion
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
newItems = [newItems copy];
|
||||||
|
if (!self.initialItemsRead) {
|
||||||
|
_items = newItems;
|
||||||
|
if (completion) {
|
||||||
|
completion();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL wasEmpty = (self.items.count == 0);
|
||||||
|
|
||||||
|
dispatch_async(self.diffingQueue, ^{
|
||||||
|
IGListIndexSetResult *result = IGListDiff(self.pendingItems, newItems, IGListDiffPointerPersonality);
|
||||||
|
self.pendingItems = newItems;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
id<IGListCollectionContext> ctx = self.collectionContext;
|
||||||
|
[ctx performBatchAnimated:animated updates:^{
|
||||||
|
[ctx insertInSectionController:(id)self atIndexes:result.inserts];
|
||||||
|
[ctx deleteInSectionController:(id)self atIndexes:result.deletes];
|
||||||
|
_items = newItems;
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
if (completion) {
|
||||||
|
completion();
|
||||||
|
}
|
||||||
|
// WORKAROUND for https://github.com/Instagram/IGListKit/issues/378
|
||||||
|
if (wasEmpty) {
|
||||||
|
[(IGListAdapter *)ctx performUpdatesAnimated:NO completion:nil];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
#import "PhotoFeedViewController.h"
|
#import "PhotoFeedViewController.h"
|
||||||
#import "PhotoFeedNodeController.h"
|
#import "PhotoFeedNodeController.h"
|
||||||
|
#import "PhotoFeedListKitViewController.h"
|
||||||
#import "WindowWithStatusBarUnderlay.h"
|
#import "WindowWithStatusBarUnderlay.h"
|
||||||
#import "Utilities.h"
|
#import "Utilities.h"
|
||||||
|
|
||||||
@@ -37,13 +38,19 @@
|
|||||||
_window = [[WindowWithStatusBarUnderlay alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
_window = [[WindowWithStatusBarUnderlay alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
_window.backgroundColor = [UIColor whiteColor];
|
_window.backgroundColor = [UIColor whiteColor];
|
||||||
|
|
||||||
// UIKit Home Feed viewController & navController
|
// ASDK Home Feed viewController & navController
|
||||||
PhotoFeedNodeController *asdkHomeFeedVC = [[PhotoFeedNodeController alloc] init];
|
PhotoFeedNodeController *asdkHomeFeedVC = [[PhotoFeedNodeController alloc] init];
|
||||||
UINavigationController *asdkHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:asdkHomeFeedVC];
|
UINavigationController *asdkHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:asdkHomeFeedVC];
|
||||||
asdkHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"ASDK" image:[UIImage imageNamed:@"home"] tag:0];
|
asdkHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"ASDK" image:[UIImage imageNamed:@"home"] tag:0];
|
||||||
asdkHomeFeedNavCtrl.hidesBarsOnSwipe = YES;
|
asdkHomeFeedNavCtrl.hidesBarsOnSwipe = YES;
|
||||||
|
|
||||||
// ASDK Home Feed viewController & navController
|
// ListKit Home Feed viewController & navController
|
||||||
|
PhotoFeedListKitViewController *listKitHomeFeedVC = [[PhotoFeedListKitViewController alloc] init];
|
||||||
|
UINavigationController *listKitHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:listKitHomeFeedVC];
|
||||||
|
listKitHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"ListKit" image:[UIImage imageNamed:@"home"] tag:0];
|
||||||
|
listKitHomeFeedNavCtrl.hidesBarsOnSwipe = YES;
|
||||||
|
|
||||||
|
// UIKit Home Feed viewController & navController
|
||||||
PhotoFeedViewController *uikitHomeFeedVC = [[PhotoFeedViewController alloc] init];
|
PhotoFeedViewController *uikitHomeFeedVC = [[PhotoFeedViewController alloc] init];
|
||||||
UINavigationController *uikitHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:uikitHomeFeedVC];
|
UINavigationController *uikitHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:uikitHomeFeedVC];
|
||||||
uikitHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"UIKit" image:[UIImage imageNamed:@"home"] tag:0];
|
uikitHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"UIKit" image:[UIImage imageNamed:@"home"] tag:0];
|
||||||
@@ -51,7 +58,7 @@
|
|||||||
|
|
||||||
// UITabBarController
|
// UITabBarController
|
||||||
UITabBarController *tabBarController = [[UITabBarController alloc] init];
|
UITabBarController *tabBarController = [[UITabBarController alloc] init];
|
||||||
tabBarController.viewControllers = @[uikitHomeFeedNavCtrl, asdkHomeFeedNavCtrl];
|
tabBarController.viewControllers = @[uikitHomeFeedNavCtrl, asdkHomeFeedNavCtrl, listKitHomeFeedNavCtrl];
|
||||||
tabBarController.selectedViewController = asdkHomeFeedNavCtrl;
|
tabBarController.selectedViewController = asdkHomeFeedNavCtrl;
|
||||||
tabBarController.delegate = self;
|
tabBarController.delegate = self;
|
||||||
[[UITabBar appearance] setTintColor:[UIColor darkBlueColor]];
|
[[UITabBar appearance] setTintColor:[UIColor darkBlueColor]];
|
||||||
|
|||||||
13
examples/ASDKgram/Sample/FeedHeaderNode.h
Normal file
13
examples/ASDKgram/Sample/FeedHeaderNode.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// FeedHeaderNode.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/23/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
@interface FeedHeaderNode : ASCellNode
|
||||||
|
|
||||||
|
@end
|
||||||
35
examples/ASDKgram/Sample/FeedHeaderNode.m
Normal file
35
examples/ASDKgram/Sample/FeedHeaderNode.m
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// FeedHeaderNode.m
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/23/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "FeedHeaderNode.h"
|
||||||
|
#import "Utilities.h"
|
||||||
|
|
||||||
|
static UIEdgeInsets kFeedHeaderInset = { .top = 20, .bottom = 20, .left = 10, .right = 10 };
|
||||||
|
|
||||||
|
@interface FeedHeaderNode ()
|
||||||
|
@property (nonatomic, strong, readonly) ASTextNode *textNode;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FeedHeaderNode
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_textNode = [[ASTextNode alloc] init];
|
||||||
|
self.automaticallyManagesSubnodes = YES;
|
||||||
|
_textNode.attributedText = [NSAttributedString attributedStringWithString:@"Latest Posts" fontSize:18 color:[UIColor darkGrayColor] firstWordColor:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||||
|
{
|
||||||
|
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:kFeedHeaderInset child:_textNode];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
14
examples/ASDKgram/Sample/PhotoFeedListKitViewController.h
Normal file
14
examples/ASDKgram/Sample/PhotoFeedListKitViewController.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// PhotoFeedListKitViewController.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@interface PhotoFeedListKitViewController<ASCollectionNode> : ASViewController <PhotoFeedControllerProtocol>
|
||||||
|
|
||||||
|
@end
|
||||||
106
examples/ASDKgram/Sample/PhotoFeedListKitViewController.m
Normal file
106
examples/ASDKgram/Sample/PhotoFeedListKitViewController.m
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// PhotoFeedListKitViewController.m
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PhotoFeedListKitViewController.h"
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
#import "PhotoFeedModel.h"
|
||||||
|
#import "PhotoFeedSectionController.h"
|
||||||
|
#import "RefreshingSectionControllerType.h"
|
||||||
|
|
||||||
|
@interface PhotoFeedListKitViewController () <IGListAdapterDataSource, ASCollectionDelegate>
|
||||||
|
@property (nonatomic, strong) IGListAdapter *listAdapter;
|
||||||
|
@property (nonatomic, strong) PhotoFeedModel *photoFeed;
|
||||||
|
@property (nonatomic, strong, readonly) ASCollectionNode *collectionNode;
|
||||||
|
@property (nonatomic, strong, readonly) UIActivityIndicatorView *spinner;
|
||||||
|
@property (nonatomic, strong, readonly) UIRefreshControl *refreshCtrl;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PhotoFeedListKitViewController
|
||||||
|
@synthesize spinner = _spinner;
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||||
|
ASCollectionNode *node = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout];
|
||||||
|
if (self = [super initWithNode:node]) {
|
||||||
|
CGRect screenRect = [[UIScreen mainScreen] bounds];
|
||||||
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
||||||
|
CGSize screenWidthImageSize = CGSizeMake(screenRect.size.width * screenScale, screenRect.size.width * screenScale);
|
||||||
|
_photoFeed = [[PhotoFeedModel alloc] initWithPhotoFeedModelType:PhotoFeedModelTypePopular imageSize:screenWidthImageSize];
|
||||||
|
|
||||||
|
IGListAdapterUpdater *updater = [[IGListAdapterUpdater alloc] init];
|
||||||
|
_listAdapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:self workingRangeSize:0];
|
||||||
|
_listAdapter.dataSource = self;
|
||||||
|
[_listAdapter setASDKCollectionNode:self.collectionNode];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad
|
||||||
|
{
|
||||||
|
[super viewDidLoad];
|
||||||
|
self.collectionNode.view.alwaysBounceVertical = YES;
|
||||||
|
_refreshCtrl = [[UIRefreshControl alloc] init];
|
||||||
|
[_refreshCtrl addTarget:self action:@selector(refreshFeed) forControlEvents:UIControlEventValueChanged];
|
||||||
|
[self.collectionNode.view addSubview:_refreshCtrl];
|
||||||
|
_spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASCollectionNode *)collectionNode
|
||||||
|
{
|
||||||
|
return self.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resetAllData
|
||||||
|
{
|
||||||
|
// nop, not used currently
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)refreshFeed
|
||||||
|
{
|
||||||
|
// Ask the first section controller to do the refreshing.
|
||||||
|
id<RefreshingSectionControllerType> secCtrl = [self.listAdapter sectionControllerForObject:self.photoFeed];
|
||||||
|
if ([secCtrl conformsToProtocol:@protocol(RefreshingSectionControllerType)]) {
|
||||||
|
[secCtrl refreshContentWithCompletion:^{
|
||||||
|
[self.refreshCtrl endRefreshing];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIActivityIndicatorView *)spinner
|
||||||
|
{
|
||||||
|
if (_spinner == nil) {
|
||||||
|
_spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||||
|
[_spinner startAnimating];
|
||||||
|
}
|
||||||
|
return _spinner;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - IGListAdapterDataSource
|
||||||
|
|
||||||
|
- (NSArray<id <IGListDiffable>> *)objectsForListAdapter:(IGListAdapter *)listAdapter
|
||||||
|
{
|
||||||
|
return @[ self.photoFeed ];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)emptyViewForListAdapter:(IGListAdapter *)listAdapter
|
||||||
|
{
|
||||||
|
return self.spinner;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IGListSectionController <IGListSectionType> *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[PhotoFeedModel class]]) {
|
||||||
|
return [[PhotoFeedSectionController alloc] init];
|
||||||
|
} else {
|
||||||
|
ASDisplayNodeFailAssert(@"Only supports objects of class PhotoFeedModel.");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "PhotoModel.h"
|
#import "PhotoModel.h"
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, PhotoFeedModelType) {
|
typedef NS_ENUM(NSInteger, PhotoFeedModelType) {
|
||||||
PhotoFeedModelTypePopular,
|
PhotoFeedModelTypePopular,
|
||||||
@@ -25,11 +26,13 @@ typedef NS_ENUM(NSInteger, PhotoFeedModelType) {
|
|||||||
PhotoFeedModelTypeUserPhotos
|
PhotoFeedModelTypeUserPhotos
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface PhotoFeedModel : NSObject
|
@interface PhotoFeedModel : NSObject <IGListDiffable>
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
- (instancetype)initWithPhotoFeedModelType:(PhotoFeedModelType)type imageSize:(CGSize)size NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithPhotoFeedModelType:(PhotoFeedModelType)type imageSize:(CGSize)size NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) NSArray<PhotoModel *> *photos;
|
||||||
|
|
||||||
- (NSUInteger)totalNumberOfPhotos;
|
- (NSUInteger)totalNumberOfPhotos;
|
||||||
- (NSUInteger)numberOfItemsInFeed;
|
- (NSUInteger)numberOfItemsInFeed;
|
||||||
- (PhotoModel *)objectAtIndex:(NSUInteger)index;
|
- (PhotoModel *)objectAtIndex:(NSUInteger)index;
|
||||||
|
|||||||
@@ -47,13 +47,6 @@
|
|||||||
NSUInteger _userID;
|
NSUInteger _userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Properties
|
|
||||||
|
|
||||||
- (NSMutableArray *)photos
|
|
||||||
{
|
|
||||||
return _photos;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Lifecycle
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
- (instancetype)initWithPhotoFeedModelType:(PhotoFeedModelType)type imageSize:(CGSize)size
|
- (instancetype)initWithPhotoFeedModelType:(PhotoFeedModelType)type imageSize:(CGSize)size
|
||||||
@@ -92,6 +85,11 @@
|
|||||||
|
|
||||||
#pragma mark - Instance Methods
|
#pragma mark - Instance Methods
|
||||||
|
|
||||||
|
- (NSArray *)photos
|
||||||
|
{
|
||||||
|
return [_photos copy];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSUInteger)totalNumberOfPhotos
|
- (NSUInteger)totalNumberOfPhotos
|
||||||
{
|
{
|
||||||
return _totalItems;
|
return _totalItems;
|
||||||
@@ -186,10 +184,13 @@
|
|||||||
// early return if reached end of pages
|
// early return if reached end of pages
|
||||||
if (_totalPages) {
|
if (_totalPages) {
|
||||||
if (_currentPage == _totalPages) {
|
if (_currentPage == _totalPages) {
|
||||||
|
if (block){
|
||||||
|
block(@[]);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSUInteger numPhotos = (numResults < 100) ? numResults : 100;
|
NSUInteger numPhotos = (numResults < 100) ? numResults : 100;
|
||||||
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
@@ -246,4 +247,16 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - IGListDiffable
|
||||||
|
|
||||||
|
- (id<NSObject>)diffIdentifier
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToDiffableObject:(id<IGListDiffable>)object
|
||||||
|
{
|
||||||
|
return self == object;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
24
examples/ASDKgram/Sample/PhotoFeedSectionController.h
Normal file
24
examples/ASDKgram/Sample/PhotoFeedSectionController.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// PhotoFeedSectionController.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
#import "RefreshingSectionControllerType.h"
|
||||||
|
#import "ASCollectionSectionController.h"
|
||||||
|
|
||||||
|
@class PhotoFeedModel;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PhotoFeedSectionController : ASCollectionSectionController <IGListSectionType, ASSectionController, RefreshingSectionControllerType>
|
||||||
|
|
||||||
|
@property (nonatomic, strong, nullable) PhotoFeedModel *photoFeed;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
122
examples/ASDKgram/Sample/PhotoFeedSectionController.m
Normal file
122
examples/ASDKgram/Sample/PhotoFeedSectionController.m
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// PhotoFeedSectionController.m
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PhotoFeedSectionController.h"
|
||||||
|
#import "PhotoFeedModel.h"
|
||||||
|
#import "PhotoModel.h"
|
||||||
|
#import "PhotoCellNode.h"
|
||||||
|
#import "TailLoadingNode.h"
|
||||||
|
#import "FeedHeaderNode.h"
|
||||||
|
|
||||||
|
@interface PhotoFeedSectionController () <ASSupplementaryNodeSource, IGListSupplementaryViewSource>
|
||||||
|
@property (nonatomic, strong) NSString *paginatingSpinner;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PhotoFeedSectionController
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_paginatingSpinner = @"Paginating Spinner";
|
||||||
|
self.supplementaryViewSource = self;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - IGListSectionType
|
||||||
|
|
||||||
|
- (void)didUpdateToObject:(id)object
|
||||||
|
{
|
||||||
|
_photoFeed = object;
|
||||||
|
[self setItems:_photoFeed.photos animated:NO completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ASIGSectionControllerSizeForItemImplementation;
|
||||||
|
ASIGSectionControllerCellForIndexImplementation;
|
||||||
|
|
||||||
|
- (void)didSelectItemAtIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
// nop
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASSectionController
|
||||||
|
|
||||||
|
- (ASCellNodeBlock)nodeBlockForItemAtIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
id object = self.items[index];
|
||||||
|
// this will be executed on a background thread - important to make sure it's thread safe
|
||||||
|
ASCellNode *(^nodeBlock)() = nil;
|
||||||
|
if (object == _paginatingSpinner) {
|
||||||
|
nodeBlock = ^{
|
||||||
|
return [[TailLoadingNode alloc] init];
|
||||||
|
};
|
||||||
|
} else if ([object isKindOfClass:[PhotoModel class]]) {
|
||||||
|
PhotoModel *photoModel = object;
|
||||||
|
nodeBlock = ^{
|
||||||
|
PhotoCellNode *cellNode = [[PhotoCellNode alloc] initWithPhotoObject:photoModel];
|
||||||
|
return cellNode;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)beginBatchFetchWithContext:(ASBatchContext *)context
|
||||||
|
{
|
||||||
|
// Immediately add the loading spinner if needed.
|
||||||
|
if (self.items.count > 0) {
|
||||||
|
NSArray *newItems = [self.items arrayByAddingObject:_paginatingSpinner];
|
||||||
|
[self setItems:newItems animated:NO completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the fetch, then update the items (removing the spinner) when they are loaded.
|
||||||
|
[_photoFeed requestPageWithCompletionBlock:^(NSArray *newPhotos){
|
||||||
|
[self setItems:_photoFeed.photos animated:NO completion:^{
|
||||||
|
[context completeBatchFetching:YES];
|
||||||
|
}];
|
||||||
|
} numResultsToReturn:20];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - RefreshingSectionControllerType
|
||||||
|
|
||||||
|
- (void)refreshContentWithCompletion:(void(^)())completion
|
||||||
|
{
|
||||||
|
[_photoFeed refreshFeedWithCompletionBlock:^(NSArray *addedItems) {
|
||||||
|
[self setItems:_photoFeed.photos animated:YES completion:completion];
|
||||||
|
} numResultsToReturn:4];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASSupplementaryNodeSource
|
||||||
|
|
||||||
|
- (ASCellNode *)nodeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert([elementKind isEqualToString:UICollectionElementKindSectionHeader], nil);
|
||||||
|
return [[FeedHeaderNode alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASSizeRange)sizeRangeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index
|
||||||
|
{
|
||||||
|
if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) {
|
||||||
|
return ASSizeRangeUnconstrained;
|
||||||
|
} else {
|
||||||
|
return ASSizeRangeZero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - IGListSupplementaryViewSource
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)supportedElementKinds
|
||||||
|
{
|
||||||
|
return @[ UICollectionElementKindSectionHeader ];
|
||||||
|
}
|
||||||
|
|
||||||
|
ASIGSupplementarySourceViewForSupplementaryElementImplementation(self);
|
||||||
|
ASIGSupplementarySourceSizeForSupplementaryElementImplementation;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -17,12 +17,12 @@
|
|||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "CoreGraphics/CoreGraphics.h"
|
|
||||||
#import "UserModel.h"
|
#import "UserModel.h"
|
||||||
#import "LocationModel.h"
|
#import "LocationModel.h"
|
||||||
#import "CommentFeedModel.h"
|
#import "CommentFeedModel.h"
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
@interface PhotoModel : NSObject
|
@interface PhotoModel : NSObject <IGListDiffable>
|
||||||
|
|
||||||
@property (nonatomic, strong, readonly) NSURL *URL;
|
@property (nonatomic, strong, readonly) NSURL *URL;
|
||||||
@property (nonatomic, strong, readonly) NSString *photoID;
|
@property (nonatomic, strong, readonly) NSString *photoID;
|
||||||
|
|||||||
@@ -83,11 +83,7 @@
|
|||||||
|
|
||||||
- (NSAttributedString *)likesAttributedStringWithFontSize:(CGFloat)size
|
- (NSAttributedString *)likesAttributedStringWithFontSize:(CGFloat)size
|
||||||
{
|
{
|
||||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
NSString *likesString = [NSString stringWithFormat:@"♥︎ %lu likes", (unsigned long)_likesCount];
|
||||||
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
|
|
||||||
NSString *formattedLikesNumber = [formatter stringFromNumber:[[NSNumber alloc] initWithUnsignedInteger:self.likesCount]];
|
|
||||||
|
|
||||||
NSString *likesString = [NSString stringWithFormat:@"♥︎ %@ likes", formattedLikesNumber];
|
|
||||||
|
|
||||||
return [NSAttributedString attributedStringWithString:likesString fontSize:size color:[UIColor darkBlueColor] firstWordColor:nil];
|
return [NSAttributedString attributedStringWithString:likesString fontSize:size color:[UIColor darkBlueColor] firstWordColor:nil];
|
||||||
}
|
}
|
||||||
@@ -102,4 +98,14 @@
|
|||||||
return [NSString stringWithFormat:@"%@ - %@", _photoID, _descriptionText];
|
return [NSString stringWithFormat:@"%@ - %@", _photoID, _descriptionText];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
- (id<NSObject>)diffIdentifier
|
||||||
|
{
|
||||||
|
return self.photoID;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToDiffableObject:(id<IGListDiffable>)object
|
||||||
|
{
|
||||||
|
return [self isEqual:object];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
19
examples/ASDKgram/Sample/RefreshingSectionControllerType.h
Normal file
19
examples/ASDKgram/Sample/RefreshingSectionControllerType.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// RefreshingSectionControllerType.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 12/29/16.
|
||||||
|
// Copyright © 2016 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IGListKit/IGListKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol RefreshingSectionControllerType <IGListSectionType>
|
||||||
|
|
||||||
|
- (void)refreshContentWithCompletion:(nullable void(^)())completion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
17
examples/ASDKgram/Sample/TailLoadingNode.h
Normal file
17
examples/ASDKgram/Sample/TailLoadingNode.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// TailLoadingNode.h
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/3/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node that shows a UIActivityIndicatorView, useful for putting at the end of a
|
||||||
|
* list while the next page is loading.
|
||||||
|
*/
|
||||||
|
@interface TailLoadingNode : ASCellNode
|
||||||
|
|
||||||
|
@end
|
||||||
35
examples/ASDKgram/Sample/TailLoadingNode.m
Normal file
35
examples/ASDKgram/Sample/TailLoadingNode.m
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// TailLoadingNode.m
|
||||||
|
// Sample
|
||||||
|
//
|
||||||
|
// Created by Adlai Holler on 1/3/17.
|
||||||
|
// Copyright © 2017 Facebook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TailLoadingNode.h"
|
||||||
|
|
||||||
|
@interface TailLoadingNode ()
|
||||||
|
@property (nonatomic, strong) ASDisplayNode *activityIndicatorNode;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TailLoadingNode
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_activityIndicatorNode = [[ASDisplayNode alloc] initWithViewBlock:^{
|
||||||
|
UIActivityIndicatorView *v = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||||
|
[v startAnimating];
|
||||||
|
return v;
|
||||||
|
}];
|
||||||
|
self.style.height = ASDimensionMake(100);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||||
|
{
|
||||||
|
return [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionMinimumXY child:self.activityIndicatorNode];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Reference in New Issue
Block a user