Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a576a83530 | |||
| 4949a88839 | |||
| 11e0c80586 | |||
| 0037147caf | |||
| 35543f6b6c | |||
| 227269190f | |||
| 38f6b056f1 | |||
| 90a0ce56da | |||
| 0e9d75b59d | |||
| da9c8b1372 | |||
| 83960eb567 | |||
| cae11d5404 | |||
| ab7324dc5b | |||
| 8cd7e843af | |||
| 519d724e17 | |||
| d80114e454 | |||
| 1d4c698ab0 | |||
| 0ebf480310 | |||
| b178f69898 | |||
| 62782d83f9 | |||
| b3038a90ec | |||
| 03ba583c49 | |||
| f29e4b0716 | |||
| 41ce466ae3 | |||
| c3688a9e1d | |||
| 512885a166 | |||
| 8fad95711e | |||
| d6e792e3ec | |||
| fcea3c29e7 | |||
| 7eb29bd82a | |||
| a64002ef72 | |||
| d3d5136f3d | |||
| 8691a862bc | |||
| e4378462e2 | |||
| a8b2962c9b | |||
| 31f9b56b3a | |||
| 51473be4c7 | |||
| ee26e28d39 | |||
| f6b339ad96 | |||
| cc916ccd92 | |||
| ae1969e26f | |||
| 42e8d150a2 | |||
| b839a5af47 | |||
| a522cf0c36 | |||
| 294fd763f8 | |||
| 9468de35bd | |||
| e95b550962 | |||
| f8adf9c9a5 | |||
| 29de021e92 | |||
| e011a23f19 | |||
| 12f4c3e966 | |||
| af0c4598be | |||
| a446dc45ff |
@@ -33,3 +33,4 @@ Carthage
|
||||
# Pods/
|
||||
/Example/InfiniteLayout.xcworkspace
|
||||
/Example/Pods
|
||||
/Example/InfiniteLayout.xcodeproj/project.xcworkspace/xcshareddata
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
4.0
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
+7
-8
@@ -2,13 +2,12 @@
|
||||
# * http://www.objc.io/issue-6/travis-ci.html
|
||||
# * https://github.com/supermarin/xcpretty#usage
|
||||
|
||||
osx_image: xcode7.3
|
||||
language: objective-c
|
||||
# cache: cocoapods
|
||||
# podfile: Example/Podfile
|
||||
# before_install:
|
||||
# - gem install cocoapods # Since Travis is not always on latest version
|
||||
# - pod install --project-directory=Example
|
||||
osx_image: xcode10.2
|
||||
language: swift
|
||||
before_install:
|
||||
- gem install cocoapods # Since Travis is not always on latest version
|
||||
- pod repo update
|
||||
- pod install --project-directory=Example
|
||||
script:
|
||||
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/InfiniteLayout.xcworkspace -scheme InfiniteLayout-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||
- set -o pipefail && xcodebuild -workspace Example/InfiniteLayout.xcworkspace -scheme InfiniteLayout-Example -sdk iphonesimulator build CODE_SIGNING_REQUIRED=NO | xcpretty -c
|
||||
- pod lib lint
|
||||
|
||||
@@ -226,7 +226,6 @@
|
||||
607FACCD1AFB9204008FA782 /* Frameworks */,
|
||||
607FACCE1AFB9204008FA782 /* Resources */,
|
||||
36EEEA4F62F7A41DC7E00F9B /* [CP] Embed Pods Frameworks */,
|
||||
BF7EA699B063C96A45D69BF2 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -245,8 +244,6 @@
|
||||
607FACE11AFB9204008FA782 /* Sources */,
|
||||
607FACE21AFB9204008FA782 /* Frameworks */,
|
||||
607FACE31AFB9204008FA782 /* Resources */,
|
||||
066936A649BBA50B7D22FE7E /* [CP] Embed Pods Frameworks */,
|
||||
56B85F2D241E5ED6DDCED73C /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -265,18 +262,18 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 0830;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = CocoaPods;
|
||||
TargetAttributes = {
|
||||
607FACCF1AFB9204008FA782 = {
|
||||
CreatedOnToolsVersion = 6.3.1;
|
||||
DevelopmentTeam = CPE39ZT2AY;
|
||||
LastSwiftMigration = 0900;
|
||||
LastSwiftMigration = 1020;
|
||||
};
|
||||
607FACE41AFB9204008FA782 = {
|
||||
CreatedOnToolsVersion = 6.3.1;
|
||||
DevelopmentTeam = CPE39ZT2AY;
|
||||
LastSwiftMigration = 0900;
|
||||
LastSwiftMigration = 1020;
|
||||
TestTargetID = 607FACCF1AFB9204008FA782;
|
||||
};
|
||||
};
|
||||
@@ -286,6 +283,7 @@
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
@@ -321,62 +319,32 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
066936A649BBA50B7D22FE7E /* [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-InfiniteLayout_Tests/Pods-InfiniteLayout_Tests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
36EEEA4F62F7A41DC7E00F9B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/CocoaProxy/CocoaProxy.framework",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/Differentiator/Differentiator.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/InfiniteLayout/InfiniteLayout.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RxDataSources/RxDataSources.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RxRelay/RxRelay.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaProxy.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Differentiator.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/InfiniteLayout.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxDataSources.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRelay.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
56B85F2D241E5ED6DDCED73C /* [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-InfiniteLayout_Tests/Pods-InfiniteLayout_Tests-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-InfiniteLayout_Example/Pods-InfiniteLayout_Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
BB5E5FB53E7C451064DBC9A2 /* [CP] Check Pods Manifest.lock */ = {
|
||||
@@ -397,21 +365,6 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
BF7EA699B063C96A45D69BF2 /* [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-InfiniteLayout_Example/Pods-InfiniteLayout_Example-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DF297DCD753BC67E73166377 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -489,6 +442,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -497,12 +451,14 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
@@ -535,6 +491,7 @@
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -542,6 +499,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -550,12 +508,14 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
@@ -580,6 +540,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
@@ -595,8 +556,8 @@
|
||||
MODULE_NAME = ExampleApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -611,8 +572,8 @@
|
||||
MODULE_NAME = ExampleApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -633,8 +594,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -651,8 +611,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
+1
-3
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0900"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -40,7 +40,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
@@ -70,7 +69,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<scene sceneID="l4I-9G-XdF">
|
||||
<objects>
|
||||
<navigationController id="yGQ-hH-2v6" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="IdE-R7-9TG">
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="44"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="IdE-R7-9TG">
|
||||
<rect key="frame" x="0.0" y="20" width="320" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
@@ -98,14 +98,18 @@
|
||||
<segue destination="ctO-Ld-yhL" kind="show" id="qss-AL-dgi"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Delegate" id="lpd-Xl-djA">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="c9c-gc-NDL" style="IBUITableViewCellStyleDefault" id="7Dq-og-5lN">
|
||||
<rect key="frame" x="0.0" y="132" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="160" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7Dq-og-5lN" id="XGb-gg-zbn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Picker" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c9c-gc-NDL">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Horizontal Picker" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c9c-gc-NDL">
|
||||
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
@@ -123,7 +127,7 @@
|
||||
<tableViewSection headerTitle="Rx" id="l6q-RG-uyY">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="i8W-08-UPB" style="IBUITableViewCellStyleDefault" id="1E8-fo-BBx">
|
||||
<rect key="frame" x="0.0" y="204" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="232" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1E8-fo-BBx" id="NMq-kd-IrV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
@@ -203,6 +207,9 @@
|
||||
</cells>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="isItemPagingEnabled" value="YES"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="velocityMultiplier">
|
||||
<real key="value" value="500"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="ctO-Ld-yhL" id="bXu-Jz-K7t"/>
|
||||
@@ -218,14 +225,14 @@
|
||||
<constraint firstItem="enX-ef-ELn" firstAttribute="leading" secondItem="C5p-bu-Djh" secondAttribute="leading" id="uX4-ox-gnL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Custom Layout" id="hZl-1w-5Nq"/>
|
||||
<navigationItem key="navigationItem" title="Custom Layout" largeTitleDisplayMode="never" id="hZl-1w-5Nq"/>
|
||||
<connections>
|
||||
<outlet property="infiniteCollectionView" destination="enX-ef-ELn" id="jKo-DT-4uH"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4s9-AY-FII" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-770" y="802"/>
|
||||
<point key="canvasLocation" x="21" y="788"/>
|
||||
</scene>
|
||||
<!--Infinite Delegate-->
|
||||
<scene sceneID="HqS-9O-oG4">
|
||||
@@ -313,7 +320,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="jlK-LR-KNy" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="22" y="802"/>
|
||||
<point key="canvasLocation" x="784" y="-664"/>
|
||||
</scene>
|
||||
<!--Rx-->
|
||||
<scene sceneID="w7X-Gq-cbX">
|
||||
@@ -371,14 +378,14 @@
|
||||
<constraint firstAttribute="bottom" secondItem="ci9-0n-fka" secondAttribute="bottom" id="yOo-Td-V0c"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Rx" id="BMY-0d-YCj"/>
|
||||
<navigationItem key="navigationItem" title="Rx" largeTitleDisplayMode="never" id="BMY-0d-YCj"/>
|
||||
<connections>
|
||||
<outlet property="infiniteCollectionView" destination="ci9-0n-fka" id="fSY-Qh-bhA"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="TkU-4C-L7I" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-770" y="-671"/>
|
||||
<point key="canvasLocation" x="784" y="60"/>
|
||||
</scene>
|
||||
<!--Horizontal Layout-->
|
||||
<scene sceneID="0Xz-LA-moA">
|
||||
@@ -396,7 +403,7 @@
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="BVQ-cb-bj4" customClass="Cell" customModule="InfiniteLayout_Example" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="177" width="250" height="150"/>
|
||||
<rect key="frame" x="0.0" y="151" width="250" height="150"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="250" height="150"/>
|
||||
@@ -421,9 +428,6 @@
|
||||
</cells>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="isItemPagingEnabled" value="YES"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="velocityMultiplier">
|
||||
<real key="value" value="1"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="CU7-Hg-6kG" id="BOZ-dL-WLG"/>
|
||||
@@ -434,7 +438,7 @@
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Dsp-JP-Q6i" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="21" y="-670"/>
|
||||
<point key="canvasLocation" x="21" y="-664"/>
|
||||
</scene>
|
||||
<!--Vertical Layout-->
|
||||
<scene sceneID="ccn-9j-1sQ">
|
||||
@@ -483,7 +487,7 @@
|
||||
<outlet property="delegate" destination="9P2-Ud-D2M" id="ns0-fe-DSq"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" title="Vertical Layout" id="2E2-oh-ELb"/>
|
||||
<navigationItem key="navigationItem" title="Vertical Layout" largeTitleDisplayMode="never" id="2E2-oh-ELb"/>
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Lvb-qy-gZV" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
|
||||
@@ -22,4 +22,8 @@ class BaseCollectionViewController: InfiniteCollectionViewController {
|
||||
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return 20
|
||||
}
|
||||
|
||||
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
collectionView.scrollToItem(at: indexPath, at: self.infiniteCollectionView!.infiniteLayout.scrollDirection == .vertical ? .centeredVertically : .centeredHorizontally, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ enum CellStyle {
|
||||
let colors = [#colorLiteral(red: 0.5254901961, green: 0.6901960784, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.6196078431, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.6078431373, green: 0.5254901961, blue: 0.9137254902, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.5254901961, blue: 0.8392156863, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.5254901961, blue: 0.6, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.6784313725, blue: 0.5254901961, alpha: 1), #colorLiteral(red: 0.9137254902, green: 0.9058823529, blue: 0.5254901961, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.9137254902, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.5254901961, green: 0.8, blue: 0.9137254902, alpha: 1)]
|
||||
|
||||
@IBInspectable var styleIndex: Int {
|
||||
get { return CellStyle.all.index(of: style)! }
|
||||
get { return CellStyle.all.firstIndex(of: style)! }
|
||||
set { style = CellStyle.all[newValue % CellStyle.all.count] }
|
||||
}
|
||||
|
||||
|
||||
@@ -12,16 +12,13 @@ import InfiniteLayout
|
||||
class CustomViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var infiniteCollectionView: InfiniteCollectionView!
|
||||
|
||||
}
|
||||
|
||||
extension CustomViewController: UICollectionViewDataSource {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return 14
|
||||
}
|
||||
|
||||
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
return 2
|
||||
return 20
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
@@ -31,6 +28,13 @@ extension CustomViewController: UICollectionViewDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
extension CustomViewController: UICollectionViewDelegate {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension CustomViewController: UICollectionViewDelegateFlowLayout {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
|
||||
@@ -30,6 +30,13 @@ extension PickerController: UICollectionViewDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
extension PickerController: UICollectionViewDelegate {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension PickerController: InfiniteCollectionViewDelegate {
|
||||
|
||||
func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?) {
|
||||
|
||||
@@ -29,11 +29,13 @@ class RxBaseCollectionViewController: UIViewController {
|
||||
infiniteCollectionView.rx.modelCentered(Int.self)
|
||||
.asDriver()
|
||||
.drive(onNext: { current in
|
||||
guard let current = current else {
|
||||
print("centered: none")
|
||||
return
|
||||
}
|
||||
print("centered: \(current + 1)")
|
||||
}).disposed(by: disposeBag)
|
||||
|
||||
infiniteCollectionView.rx.itemSelected
|
||||
.asDriver()
|
||||
.drive(onNext: { [unowned self] indexPath in
|
||||
self.infiniteCollectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
|
||||
}).disposed(by: disposeBag)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,4 +1,5 @@
|
||||
use_frameworks!
|
||||
platform :ios, '10.0'
|
||||
|
||||
target 'InfiniteLayout_Example' do
|
||||
pod 'InfiniteLayout', :path => '../'
|
||||
@@ -6,7 +7,5 @@ target 'InfiniteLayout_Example' do
|
||||
|
||||
target 'InfiniteLayout_Tests' do
|
||||
inherit! :search_paths
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
+38
-28
@@ -1,40 +1,50 @@
|
||||
PODS:
|
||||
- CocoaProxy (0.1.1)
|
||||
- Differentiator (3.0.2)
|
||||
- InfiniteLayout (0.1.6):
|
||||
- CocoaProxy (~> 0.1)
|
||||
- InfiniteLayout/Core (= 0.1.6)
|
||||
- InfiniteLayout/Core (0.1.6):
|
||||
- CocoaProxy (~> 0.1)
|
||||
- InfiniteLayout/Rx (0.1.6):
|
||||
- CocoaProxy (~> 0.1)
|
||||
- RxCocoa (~> 4.0)
|
||||
- RxDataSources (~> 3.0)
|
||||
- RxSwift (~> 4.0)
|
||||
- RxCocoa (4.1.0):
|
||||
- RxSwift (~> 4.0)
|
||||
- RxDataSources (3.0.2):
|
||||
- Differentiator (~> 3.0)
|
||||
- RxCocoa (~> 4.0)
|
||||
- RxSwift (~> 4.0)
|
||||
- RxSwift (4.1.0)
|
||||
- Differentiator (5.0.0)
|
||||
- InfiniteLayout (0.5):
|
||||
- InfiniteLayout/Core (= 0.5)
|
||||
- InfiniteLayout/CocoaProxy (0.5)
|
||||
- InfiniteLayout/Core (0.5):
|
||||
- InfiniteLayout/CocoaProxy
|
||||
- InfiniteLayout/Rx (0.5):
|
||||
- InfiniteLayout/Core
|
||||
- RxCocoa (~> 6)
|
||||
- RxDataSources (~> 5)
|
||||
- RxSwift (~> 6)
|
||||
- RxCocoa (6.2.0):
|
||||
- RxRelay (= 6.2.0)
|
||||
- RxSwift (= 6.2.0)
|
||||
- RxDataSources (5.0.0):
|
||||
- Differentiator (~> 5.0)
|
||||
- RxCocoa (~> 6.0)
|
||||
- RxSwift (~> 6.0)
|
||||
- RxRelay (6.2.0):
|
||||
- RxSwift (= 6.2.0)
|
||||
- RxSwift (6.2.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- InfiniteLayout (from `../`)
|
||||
- InfiniteLayout/Rx (from `../`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Differentiator
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
- RxRelay
|
||||
- RxSwift
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
InfiniteLayout:
|
||||
:path: ../
|
||||
:path: "../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
CocoaProxy: 35ab81e24325b33834cffe45a3d1fd48ca67ef3a
|
||||
Differentiator: a87be69eba49ec4ab460c7671143ee3a9eececfd
|
||||
InfiniteLayout: 27a10e0a766122807a73740b5e7c7384fcdc37a2
|
||||
RxCocoa: cc1fec49cdc8fabe645964de7c51c099a36c2aa8
|
||||
RxDataSources: cb7c31e652a87ebb919da45f716bbb87b3765f6b
|
||||
RxSwift: 4219941c1244c88002901bd87a69d3aea9ae71f0
|
||||
Differentiator: e8497ceab83c1b10ca233716d547b9af21b9344d
|
||||
InfiniteLayout: 2c55b0fc14b6a9d924fbe13c0e2d88b1cbf5423d
|
||||
RxCocoa: 4baf94bb35f2c0ab31bc0cb9f1900155f646ba42
|
||||
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
||||
RxRelay: e72dbfd157807478401ef1982e1c61c945c94b2f
|
||||
RxSwift: d356ab7bee873611322f134c5f9ef379fa183d8f
|
||||
|
||||
PODFILE CHECKSUM: 3501aeed91e62112dd38178a52f26b204b97c8c0
|
||||
PODFILE CHECKSUM: 0dc7a9b37f9b7c5d5266beaab9e94861b80aa80f
|
||||
|
||||
COCOAPODS: 1.4.0.rc.1
|
||||
COCOAPODS: 1.10.1
|
||||
|
||||
+24
-20
@@ -8,8 +8,8 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'InfiniteLayout'
|
||||
s.version = '0.1.7'
|
||||
s.summary = 'Horizontal and Vertical infinite scrolling feature for UICollectionView'
|
||||
s.version = '0.5'
|
||||
s.summary = 'Horizontal and Vertical infinite scrolling feature for UICollectionView with Paging, NSProxy delegate, Reactive extension'
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
# * Think: What does it do? Why did you write it? What is the focus?
|
||||
@@ -18,19 +18,19 @@ Pod::Spec.new do |s|
|
||||
# * Finally, don't worry about the indent, CocoaPods strips it!
|
||||
|
||||
s.description = <<-DESC
|
||||
Horizontal and Vertical infinite scrolling feature for UICollectionView with Paging and NSProxy delegate
|
||||
Horizontal and Vertical infinite scrolling feature for UICollectionView with Paging, NSProxy delegate, Reactive extension, SectionModel & AnimatableSectionModel support
|
||||
DESC
|
||||
|
||||
s.homepage = 'https://github.com/Arnoymous/InfiniteLayout'
|
||||
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
|
||||
s.homepage = 'https://github.com/arnauddorgans/InfiniteLayout'
|
||||
s.screenshots = 'https://github.com/arnauddorgans/InfiniteLayout/raw/master/horizontal.gif', 'https://github.com/arnauddorgans/InfiniteLayout/raw/master/vertical.gif', 'https://github.com/arnauddorgans/InfiniteLayout/raw/master/custom.gif', 'https://github.com/arnauddorgans/InfiniteLayout/raw/master/delegate.gif'
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
s.author = { 'Arnoymous' => 'ineox@me.com' }
|
||||
s.source = { :git => 'https://github.com/Arnoymous/InfiniteLayout.git', :tag => s.version.to_s }
|
||||
s.author = { 'Arnaud Dorgans' => 'ineox@me.com' }
|
||||
s.source = { :git => 'https://github.com/arnauddorgans/InfiniteLayout.git', :tag => s.version.to_s }
|
||||
s.social_media_url = 'https://twitter.com/arnauddorgans'
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.tvos.deployment_target = '9.0'
|
||||
|
||||
|
||||
#s.xcconfig = { 'SWIFT_OBJC_BRIDGING_HEADER' => '${POD_ROOT}/InfiniteLayout/BridgeHeader.h' }
|
||||
|
||||
# s.resource_bundles = {
|
||||
@@ -39,19 +39,23 @@ Horizontal and Vertical infinite scrolling feature for UICollectionView with Pag
|
||||
|
||||
# s.public_header_files = 'Pod/Classes/**/*.h'
|
||||
# s.frameworks = 'UIKit', 'MapKit'
|
||||
s.dependency 'CocoaProxy', '~> 0.1'
|
||||
s.swift_versions = ['5.0', '5.1']
|
||||
|
||||
|
||||
s.default_subspec = 'Core'
|
||||
|
||||
s.subspec 'Core' do |sp|
|
||||
s.source_files = 'InfiniteLayout/Classes/**/*'
|
||||
s.subspec 'Core' do |core|
|
||||
core.source_files = 'Sources/InfiniteLayout/**/*'
|
||||
core.dependency 'InfiniteLayout/CocoaProxy'
|
||||
core.exclude_files = '**/*/SPMBridge.swift'
|
||||
end
|
||||
|
||||
s.subspec 'Rx' do |sp|
|
||||
sp.dependency 'InfiniteLayout/Core', '~> 0.1'
|
||||
sp.dependency 'RxSwift', '~> 4.0'
|
||||
sp.dependency 'RxCocoa', '~> 4.0'
|
||||
sp.dependency 'RxDataSources', '~> 3.0'
|
||||
sp.source_files = 'InfiniteLayout/Rx/**/*'
|
||||
s.subspec 'CocoaProxy' do |core|
|
||||
core.source_files = 'Sources/CocoaProxy/**/*'
|
||||
end
|
||||
s.subspec 'Rx' do |rx|
|
||||
rx.dependency 'InfiniteLayout/Core'
|
||||
rx.dependency 'RxSwift', '~> 6'
|
||||
rx.dependency 'RxCocoa', '~> 6'
|
||||
rx.dependency 'RxDataSources', '~> 5'
|
||||
rx.source_files = 'Sources/Rx/**/*'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// swift-tools-version:5.0
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "InfiniteLayout",
|
||||
platforms: [.iOS(.v9), .tvOS(.v9)],
|
||||
products: [
|
||||
.library(
|
||||
name: "InfiniteLayout",
|
||||
targets: ["InfiniteLayout"]),
|
||||
.library(
|
||||
name: "RxInfiniteLayout",
|
||||
targets: ["RxInfiniteLayout"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "6.0.0")),
|
||||
.package(url: "https://github.com/RxSwiftCommunity/RxDataSources.git", .upToNextMajor(from: "5.0.0")),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "CocoaProxy",
|
||||
dependencies: [],
|
||||
publicHeadersPath: "./"
|
||||
),
|
||||
.target(
|
||||
name: "InfiniteLayout",
|
||||
dependencies: ["CocoaProxy"]
|
||||
),
|
||||
.target(
|
||||
name: "RxInfiniteLayout",
|
||||
dependencies: ["InfiniteLayout", "RxSwift", "RxCocoa", "RxDataSources"],
|
||||
path: "Sources/Rx"
|
||||
),
|
||||
]
|
||||
)
|
||||
@@ -1,18 +1,22 @@
|
||||
# InfiniteLayout
|
||||
|
||||
[](https://travis-ci.org/Arnoymous/InfiniteLayout)
|
||||
[](http://cocoapods.org/pods/InfiniteLayout)
|
||||
[](https://travis-ci.org/arnauddorgans/InfiniteLayout)
|
||||
[](http://cocoapods.org/pods/InfiniteLayout)
|
||||
[](http://cocoapods.org/pods/InfiniteLayout)
|
||||
[](http://cocoapods.org/pods/InfiniteLayout)
|
||||
[](https://github.com/apple/swift-package-manager)
|
||||
|
||||
<img src="https://github.com/arnauddorgans/InfiniteLayout/raw/master/horizontal.gif" width="250" height="540"><img src="https://github.com/arnauddorgans/InfiniteLayout/raw/master/vertical.gif" width="250" height="540"><img src="https://github.com/arnauddorgans/InfiniteLayout/raw/master/custom.gif" width="250" height="540">
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
To run the example project, clone the repo, and run `pod install` from the Example directory first.
|
||||
|
||||
## Requirements
|
||||
|
||||
## Installation
|
||||
|
||||
### [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html)
|
||||
|
||||
InfiniteLayout is available through [CocoaPods](http://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
|
||||
@@ -20,6 +24,27 @@ it, simply add the following line to your Podfile:
|
||||
pod 'InfiniteLayout'
|
||||
```
|
||||
|
||||
|
||||
### [Swift Package Manager](https://github.com/apple/swift-package-manager)
|
||||
|
||||
Create a `Package.swift` file.
|
||||
|
||||
```swift
|
||||
// swift-tools-version:5.0
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "InfiniteLayoutTestProject",
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/arnauddorgans/InfiniteLayout.git", from: "0.4.2")
|
||||
],
|
||||
targets: [
|
||||
.target(name: "InfiniteLayoutTestProject", dependencies: ["InfiniteLayout"])
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```swift
|
||||
@@ -75,12 +100,14 @@ self.infiniteCollectionView.preferredCenteredIndexPath = [0, 0] // center the ce
|
||||
self.infiniteCollectionView.preferredCenteredIndexPath = nil // center the closest cell from center
|
||||
```
|
||||
|
||||
### Centered IndexPath
|
||||
### Delegate
|
||||
|
||||
<img src="https://github.com/arnauddorgans/InfiniteLayout/raw/master/delegate.gif" width="250" height="540">
|
||||
|
||||
InfiniteCollectionView provide an **infiniteDelegate** protocol used to get the centered IndexPath, usefull if you want to use an InfiniteCollectionView like a Picker.
|
||||
|
||||
```swift
|
||||
func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?)
|
||||
func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath from: IndexPath?, to: IndexPath?)
|
||||
```
|
||||
|
||||
### Rx
|
||||
@@ -146,20 +173,20 @@ RxInfiniteCollectionView provide Reactive extension for **itemCentered** & **mod
|
||||
```swift
|
||||
infiniteCollectionView.rx.itemCentered
|
||||
.asDriver()
|
||||
.drive(onNext: { indexPath in
|
||||
.drive(onNext: { [unowned self] indexPath in
|
||||
self.selectedView.update(index: indexPath.row) // update interface with indexPath
|
||||
}).disposed(by: disposeBag)
|
||||
|
||||
infiniteCollectionView.rx.modelCentered(Int.self)
|
||||
.asDriver()
|
||||
.drive(onNext: { element in
|
||||
.drive(onNext: { [unowned self] element in
|
||||
self.selectedView.update(index: element) // update interface with model
|
||||
}).disposed(by: disposeBag)
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
Arnoymous, arnaud.dorgans@gmail.com
|
||||
Arnaud Dorgans, arnaud.dorgans@gmail.com
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// CocoaProxy.h
|
||||
// CocoaProxy
|
||||
//
|
||||
// Created by Arnaud Dorgans on 27/12/2017.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface CocoaProxy : NSProxy
|
||||
|
||||
- (instancetype _Nonnull)init;
|
||||
- (instancetype _Nonnull)initWithProxies:(nonnull NSArray<id<NSObject>>*)proxies;
|
||||
|
||||
- (NSArray<id<NSObject>> *_Nonnull)proxiesForSelector:(SEL _Nonnull )aSelector;
|
||||
|
||||
@property (nonatomic, strong) NSArray<id<NSObject>>* _Nonnull proxies;
|
||||
@property (nonatomic, copy) BOOL (^ _Nullable proxyFilter)(id<NSObject> _Nonnull proxy, SEL _Nonnull selector);
|
||||
|
||||
@end
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// CocoaProxy.m
|
||||
// CocoaProxy
|
||||
//
|
||||
// Created by Arnaud Dorgans on 27/12/2017.
|
||||
//
|
||||
|
||||
#import "CocoaProxy.h"
|
||||
|
||||
@interface CocoaProxy () { }
|
||||
|
||||
@property (nonatomic, strong) NSPointerArray *pointerArray;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaProxy
|
||||
|
||||
- (instancetype _Nonnull)initWithProxies:(nonnull NSArray<NSObject*>*)proxies {
|
||||
[self setProxies: proxies];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)init {
|
||||
return [self initWithProxies: @[]];
|
||||
}
|
||||
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector
|
||||
{
|
||||
return ([self methodSignatureForSelector: aSelector] != nil);
|
||||
}
|
||||
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
|
||||
{
|
||||
for (NSObject* proxy in [self proxiesForSelector: aSelector]) {
|
||||
if ([proxy respondsToSelector: aSelector]) {
|
||||
return [proxy methodSignatureForSelector: aSelector];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>> *_Nonnull)proxiesForSelector:(SEL _Nonnull )aSelector
|
||||
{
|
||||
if (self.proxyFilter) {
|
||||
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||||
return self.proxyFilter(evaluatedObject, aSelector);
|
||||
}];
|
||||
return [self.proxies filteredArrayUsingPredicate: predicate];
|
||||
}
|
||||
return self.proxies;
|
||||
}
|
||||
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation
|
||||
{
|
||||
for (NSObject* proxy in [self proxiesForSelector: invocation.selector]) {
|
||||
[self invokeInvocation: invocation onProxy: proxy];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)invokeInvocation:(NSInvocation *)invocation onProxy:(id<NSObject>)proxy
|
||||
{
|
||||
if ([proxy respondsToSelector: invocation.selector]) {
|
||||
[invocation invokeWithTarget: proxy];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setProxies:(NSArray<id<NSObject>> *)proxies {
|
||||
self.pointerArray = [NSPointerArray weakObjectsPointerArray];
|
||||
for (NSObject* proxy in proxies) {
|
||||
[self.pointerArray addPointer: (void *)proxy];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>> *)proxies {
|
||||
return self.pointerArray.allObjects;
|
||||
}
|
||||
|
||||
@end
|
||||
+25
-18
@@ -8,8 +8,8 @@
|
||||
import UIKit
|
||||
|
||||
@objc public protocol InfiniteCollectionViewDelegate {
|
||||
|
||||
@objc optional func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath centeredIndexPath: IndexPath?)
|
||||
|
||||
@objc optional func infiniteCollectionView(_ infiniteCollectionView: InfiniteCollectionView, didChangeCenteredIndexPath from: IndexPath?, to: IndexPath?)
|
||||
}
|
||||
|
||||
open class InfiniteCollectionView: UICollectionView {
|
||||
@@ -17,15 +17,15 @@ open class InfiniteCollectionView: UICollectionView {
|
||||
lazy var dataSourceProxy = InfiniteCollectionViewDataSourceProxy(collectionView: self)
|
||||
lazy var delegateProxy = InfiniteCollectionViewDelegateProxy(collectionView: self)
|
||||
|
||||
@IBOutlet open var infiniteDelegate: InfiniteCollectionViewDelegate?
|
||||
@IBOutlet open weak var infiniteDelegate: InfiniteCollectionViewDelegate?
|
||||
|
||||
open private(set) var centeredIndexPath: IndexPath?
|
||||
open var preferredCenteredIndexPath: IndexPath? = IndexPath(item: 0, section: 0)
|
||||
|
||||
var forwardDelegate: Bool { return true }
|
||||
open var forwardDelegate: Bool { return true }
|
||||
var _contentSize: CGSize?
|
||||
|
||||
override open var delegate: UICollectionViewDelegate? {
|
||||
override open weak var delegate: UICollectionViewDelegate? {
|
||||
get { return super.delegate }
|
||||
set {
|
||||
guard forwardDelegate else {
|
||||
@@ -45,7 +45,7 @@ open class InfiniteCollectionView: UICollectionView {
|
||||
}
|
||||
}
|
||||
|
||||
override open var dataSource: UICollectionViewDataSource? {
|
||||
override open weak var dataSource: UICollectionViewDataSource? {
|
||||
get { return super.dataSource }
|
||||
set {
|
||||
guard forwardDelegate else {
|
||||
@@ -105,13 +105,14 @@ open class InfiniteCollectionView: UICollectionView {
|
||||
private func sharedInit() {
|
||||
self.showsVerticalScrollIndicator = false
|
||||
self.showsHorizontalScrollIndicator = false
|
||||
self.scrollsToTop = false
|
||||
#if os(iOS)
|
||||
self.scrollsToTop = false
|
||||
#endif
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
self.loopCollectionViewIfNeeded()
|
||||
self.updateLayoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +134,7 @@ extension InfiniteCollectionView: UICollectionViewDataSource {
|
||||
}
|
||||
|
||||
private var multiplier: Int {
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: self.infiniteLayout.itemSize)
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: self.infiniteLayout.itemSize, enabled: self.infiniteLayout.isEnabled)
|
||||
}
|
||||
|
||||
public func section(from infiniteSection: Int) -> Int {
|
||||
@@ -163,21 +164,26 @@ extension InfiniteCollectionView: UICollectionViewDataSource {
|
||||
|
||||
extension InfiniteCollectionView: UICollectionViewDelegate {
|
||||
|
||||
func updateLayoutIfNeeded() {
|
||||
self.loopCollectionViewIfNeeded()
|
||||
self.centerCollectionViewIfNeeded()
|
||||
|
||||
let preferredVisibleIndexPath = infiniteLayout.preferredVisibleLayoutAttributes()?.indexPath
|
||||
if self.centeredIndexPath != preferredVisibleIndexPath {
|
||||
let previousCenteredIndexPath = self.centeredIndexPath
|
||||
self.centeredIndexPath = preferredVisibleIndexPath
|
||||
self.infiniteDelegate?.infiniteCollectionView?(self, didChangeCenteredIndexPath: previousCenteredIndexPath, to: self.centeredIndexPath)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Loop
|
||||
func loopCollectionViewIfNeeded() {
|
||||
self.infiniteLayout.loopCollectionViewIfNeeded()
|
||||
self.centerCollectionViewIfNeeded()
|
||||
}
|
||||
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
delegateProxy.delegate?.scrollViewDidScroll?(scrollView)
|
||||
self.loopCollectionViewIfNeeded()
|
||||
|
||||
let preferredVisibleIndexPath = infiniteLayout.preferredVisibleLayoutAttributes()?.indexPath
|
||||
if self.centeredIndexPath != preferredVisibleIndexPath {
|
||||
self.centeredIndexPath = preferredVisibleIndexPath
|
||||
self.infiniteDelegate?.infiniteCollectionView?(self, didChangeCenteredIndexPath: preferredVisibleIndexPath)
|
||||
}
|
||||
self.updateLayoutIfNeeded()
|
||||
}
|
||||
|
||||
// MARK: Paging
|
||||
@@ -197,5 +203,6 @@ extension InfiniteCollectionView: UICollectionViewDelegate {
|
||||
if isItemPagingEnabled {
|
||||
self.infiniteLayout.centerCollectionView(withVelocity: velocity, targetContentOffset: targetContentOffset)
|
||||
}
|
||||
self.delegateProxy.delegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset)
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -6,7 +6,6 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CocoaProxy
|
||||
|
||||
class InfiniteCollectionViewProxy<T: NSObjectProtocol>: CocoaProxy {
|
||||
|
||||
@@ -45,6 +44,10 @@ class InfiniteCollectionViewProxy<T: NSObjectProtocol>: CocoaProxy {
|
||||
super.init(proxies: [])
|
||||
self.collectionView = collectionView
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.proxies.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
class InfiniteCollectionViewDelegateProxy: InfiniteCollectionViewProxy<UICollectionViewDelegate>, UICollectionViewDelegate {
|
||||
+14
-10
@@ -7,27 +7,31 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class InfiniteDataSources {
|
||||
|
||||
static func section(from infiniteSection: Int, numberOfSections: Int) -> Int {
|
||||
open class InfiniteDataSources {
|
||||
public static var originCount: Int = 0
|
||||
public static func section(from infiniteSection: Int, numberOfSections: Int) -> Int {
|
||||
return infiniteSection % numberOfSections
|
||||
}
|
||||
|
||||
static func indexPath(from infiniteIndexPath: IndexPath, numberOfSections: Int, numberOfItems: Int) -> IndexPath {
|
||||
|
||||
public static func indexPath(from infiniteIndexPath: IndexPath, numberOfSections: Int, numberOfItems: Int) -> IndexPath {
|
||||
return IndexPath(item: infiniteIndexPath.item % numberOfItems, section: self.section(from: infiniteIndexPath.section, numberOfSections: numberOfSections))
|
||||
}
|
||||
|
||||
static func multiplier(estimatedItemSize: CGSize) -> Int {
|
||||
|
||||
public static func multiplier(estimatedItemSize: CGSize, enabled: Bool) -> Int {
|
||||
guard enabled else {
|
||||
return 1
|
||||
}
|
||||
let min = Swift.min(estimatedItemSize.width, estimatedItemSize.height)
|
||||
let count = ceil(InfiniteLayout.minimumContentSize / min)
|
||||
return Int(count)
|
||||
}
|
||||
|
||||
static func numberOfSections(numberOfSections: Int, multiplier: Int) -> Int {
|
||||
|
||||
public static func numberOfSections(numberOfSections: Int, multiplier: Int) -> Int {
|
||||
return numberOfSections > 1 ? numberOfSections * multiplier : numberOfSections
|
||||
}
|
||||
|
||||
static func numberOfItemsInSection(numberOfItemsInSection: Int, numberOfSections: Int, multiplier: Int) -> Int {
|
||||
public static func numberOfItemsInSection(numberOfItemsInSection: Int, numberOfSections: Int, multiplier: Int) -> Int {
|
||||
originCount = numberOfItemsInSection
|
||||
return numberOfSections > 1 ? numberOfItemsInSection : numberOfItemsInSection * multiplier
|
||||
}
|
||||
}
|
||||
+40
-13
@@ -11,11 +11,24 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
|
||||
public var velocityMultiplier: CGFloat = 1 // used to simulate paging
|
||||
|
||||
private let multiplier: CGFloat = 100 // contentOffset multiplier
|
||||
private let multiplier: CGFloat = 500 // contentOffset multiplier
|
||||
|
||||
private var contentSize: CGSize = .zero
|
||||
|
||||
private (set) var isEnabled: Bool = false
|
||||
private var hasValidLayout: Bool = false
|
||||
|
||||
@IBInspectable public var isEnabled: Bool = true {
|
||||
didSet {
|
||||
self.invalidateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
public var currentPage: CGPoint {
|
||||
guard let collectionView = self.collectionView else {
|
||||
return .zero
|
||||
}
|
||||
return self.page(for: collectionView.contentOffset)
|
||||
}
|
||||
|
||||
open override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
|
||||
return true
|
||||
@@ -42,8 +55,8 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
override open func prepare() {
|
||||
let collectionViewContentSize = super.collectionViewContentSize
|
||||
self.contentSize = CGSize(width: collectionViewContentSize.width, height: collectionViewContentSize.height)
|
||||
self.isEnabled = {
|
||||
guard let collectionView = self.collectionView, collectionView.bounds != .zero else {
|
||||
self.hasValidLayout = {
|
||||
guard let collectionView = self.collectionView, collectionView.bounds != .zero, self.isEnabled else {
|
||||
return false
|
||||
}
|
||||
return (scrollDirection == .horizontal ? self.contentSize.width : self.contentSize.height) >=
|
||||
@@ -53,15 +66,22 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
}
|
||||
|
||||
override open var collectionViewContentSize: CGSize {
|
||||
guard isEnabled else {
|
||||
return super.collectionViewContentSize
|
||||
guard hasValidLayout else {
|
||||
return self.contentSize
|
||||
}
|
||||
return CGSize(width: scrollDirection == .horizontal ? self.contentSize.width * multiplier : self.contentSize.width,
|
||||
height: scrollDirection == .vertical ? self.contentSize.height * multiplier : self.contentSize.height)
|
||||
}
|
||||
|
||||
open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
||||
guard let attributes = super.layoutAttributesForItem(at: indexPath) else {
|
||||
return nil
|
||||
}
|
||||
return self.layoutAttributes(from: attributes, page: currentPage)
|
||||
}
|
||||
|
||||
override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
||||
guard isEnabled else {
|
||||
guard hasValidLayout else {
|
||||
return super.layoutAttributesForElements(in: rect)
|
||||
}
|
||||
let page = self.page(for: rect.origin)
|
||||
@@ -131,18 +151,25 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
}
|
||||
|
||||
// MARK: Loop
|
||||
private func updateContentOffset(_ offset: CGPoint) {
|
||||
guard let collectionView = self.collectionView else {
|
||||
return
|
||||
}
|
||||
collectionView.contentOffset = offset
|
||||
collectionView.layoutIfNeeded()
|
||||
}
|
||||
private func preferredContentOffset(forContentOffset contentOffset: CGPoint) -> CGPoint {
|
||||
return rect(from: CGRect(origin: contentOffset, size: .zero), page: self.page(from: .zero, offset: multiplier / 2)).origin
|
||||
}
|
||||
|
||||
public func loopCollectionViewIfNeeded() {
|
||||
guard let collectionView = self.collectionView, self.isEnabled else {
|
||||
guard let collectionView = self.collectionView, self.hasValidLayout else {
|
||||
return
|
||||
}
|
||||
let page = self.pageIndex(from: self.page(for: collectionView.contentOffset))
|
||||
let offset = self.preferredContentOffset(forContentOffset: collectionView.contentOffset)
|
||||
if (page < 2 || page > self.multiplier - 2) && collectionView.contentOffset != offset {
|
||||
collectionView.contentOffset = offset
|
||||
self.updateContentOffset(offset)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +253,7 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
}
|
||||
|
||||
public func centerCollectionView(withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||||
guard let collectionView = self.collectionView, self.isEnabled else {
|
||||
guard let collectionView = self.collectionView, self.hasValidLayout else {
|
||||
return
|
||||
}
|
||||
let newTarget = CGPoint(x: self.scrollDirection == .horizontal ? collectionView.contentOffset.x + velocity.x * velocityMultiplier : targetContentOffset.pointee.x,
|
||||
@@ -240,15 +267,15 @@ open class InfiniteLayout: UICollectionViewFlowLayout {
|
||||
}
|
||||
|
||||
public func centerCollectionViewIfNeeded(indexPath: IndexPath? = nil) {
|
||||
guard let collectionView = self.collectionView, self.isEnabled else {
|
||||
guard let collectionView = self.collectionView, self.hasValidLayout else {
|
||||
return
|
||||
}
|
||||
guard let preferredAttributes = self.preferredVisibleLayoutAttributes(indexPath: indexPath),
|
||||
let offset = self.centeredContentOffset(forRect: preferredAttributes.frame),
|
||||
let offset = self.centeredContentOffset(forRect: preferredAttributes.frame),
|
||||
collectionView.contentOffset != offset else {
|
||||
return
|
||||
}
|
||||
collectionView.contentOffset = offset
|
||||
self.updateContentOffset(offset)
|
||||
}
|
||||
|
||||
// MARK: Copy
|
||||
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// InfiniteCollectionView.swift
|
||||
// InfiniteLayout
|
||||
//
|
||||
// Created by Arnaud Dorgans on 05/09/2019.
|
||||
//
|
||||
|
||||
@_exported import CocoaProxy
|
||||
+32
-10
@@ -5,6 +5,10 @@
|
||||
// Created by Arnaud Dorgans on 03/01/2018.
|
||||
//
|
||||
|
||||
#if canImport(InfiniteLayout)
|
||||
import InfiniteLayout
|
||||
#endif
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
@@ -31,34 +35,52 @@ class RxInfiniteCollectionViewDelegate: DelegateProxy<InfiniteCollectionView, In
|
||||
}
|
||||
}
|
||||
|
||||
public extension Reactive where Base: InfiniteCollectionView {
|
||||
extension Reactive where Base: InfiniteCollectionView {
|
||||
|
||||
private var infiniteDelegate: RxInfiniteCollectionViewDelegate {
|
||||
return RxInfiniteCollectionViewDelegate.proxy(for: self.base)
|
||||
}
|
||||
|
||||
public var itemCentered: ControlEvent<IndexPath?> {
|
||||
let source = infiniteDelegate.sentMessage(#selector(InfiniteCollectionViewDelegate.infiniteCollectionView(_:didChangeCenteredIndexPath:)))
|
||||
let source = infiniteDelegate.sentMessage(#selector(InfiniteCollectionViewDelegate.infiniteCollectionView(_:didChangeCenteredIndexPath:to:)))
|
||||
.map { $0.last as? IndexPath }
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
public func modelCentered<T>(_ type: T.Type) -> ControlEvent<T?> {
|
||||
let source = itemCentered
|
||||
.map { indexPath -> T? in
|
||||
return try indexPath.flatMap { try self.model(at: $0) }
|
||||
|
||||
public func modelCentered<T>(_ type: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = itemCentered.flatMap { [weak view = self.base as InfiniteCollectionView] indexPath -> Observable<T> in
|
||||
guard let view = view, var indexPath = indexPath else {
|
||||
return Observable.empty()
|
||||
}
|
||||
|
||||
indexPath.row %= InfiniteDataSources.originCount
|
||||
return Observable.just(try view.rx.model(at: indexPath))
|
||||
}
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
public func modelSelected<T>(_ modelType: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = itemSelected.flatMap { [weak view = self.base as InfiniteCollectionView] indexPath -> Observable<T> in
|
||||
guard let view = view else {
|
||||
return Observable.empty()
|
||||
}
|
||||
|
||||
var indexPath = indexPath
|
||||
indexPath.row %= InfiniteDataSources.originCount
|
||||
return Observable.just(try view.rx.model(at: indexPath))
|
||||
}
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
}
|
||||
|
||||
public extension Reactive where Base: RxInfiniteCollectionView {
|
||||
extension Reactive where Base: RxInfiniteCollectionView {
|
||||
|
||||
public func items<S: Sequence, O: ObservableType>
|
||||
(infinite: Bool)
|
||||
-> (_ source: O)
|
||||
-> (_ cellFactory: @escaping (UICollectionView, Int, S.Iterator.Element) -> UICollectionViewCell)
|
||||
-> Disposable where O.E == S {
|
||||
-> Disposable where O.Element == S {
|
||||
return { source in
|
||||
guard infinite else {
|
||||
return self.items(source)
|
||||
@@ -76,7 +98,7 @@ public extension Reactive where Base: RxInfiniteCollectionView {
|
||||
(cellIdentifier: String, cellType: Cell.Type = Cell.self, infinite: Bool)
|
||||
-> (_ source: O)
|
||||
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
|
||||
-> Disposable where O.E == S {
|
||||
-> Disposable where O.Element == S {
|
||||
guard infinite else {
|
||||
return self.items(cellIdentifier: cellIdentifier, cellType: cellType)
|
||||
}
|
||||
+5
-1
@@ -5,6 +5,10 @@
|
||||
// Created by Arnaud Dorgans on 03/01/2018.
|
||||
//
|
||||
|
||||
#if canImport(InfiniteLayout)
|
||||
import InfiniteLayout
|
||||
#endif
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
@@ -13,7 +17,7 @@ open class RxInfiniteCollectionView: InfiniteCollectionView {
|
||||
|
||||
let disposeBag = DisposeBag()
|
||||
|
||||
override var forwardDelegate: Bool {
|
||||
override open var forwardDelegate: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
+12
-4
@@ -5,17 +5,23 @@
|
||||
// Created by Arnaud Dorgans on 03/01/2018.
|
||||
//
|
||||
|
||||
#if canImport(InfiniteLayout)
|
||||
import InfiniteLayout
|
||||
#endif
|
||||
|
||||
import UIKit
|
||||
import RxDataSources
|
||||
|
||||
open class RxInfiniteCollectionViewSectionedReloadDataSource<S: SectionModelType>: RxCollectionViewSectionedReloadDataSource<S> {
|
||||
|
||||
public var isEnabled: Bool = true
|
||||
|
||||
open override subscript(section: Int) -> S {
|
||||
let section = InfiniteDataSources.section(from: section, numberOfSections: sectionModels.count)
|
||||
return self.sectionModels[section]
|
||||
}
|
||||
|
||||
open override subscript(indexPath: IndexPath) -> I {
|
||||
open override subscript(indexPath: IndexPath) -> Item {
|
||||
get {
|
||||
let indexPath = InfiniteDataSources.indexPath(from: indexPath,
|
||||
numberOfSections: sectionModels.count,
|
||||
@@ -33,7 +39,7 @@ open class RxInfiniteCollectionViewSectionedReloadDataSource<S: SectionModelType
|
||||
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
|
||||
fatalError()
|
||||
}
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: layout.itemSize)
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: layout.itemSize, enabled: isEnabled)
|
||||
}
|
||||
|
||||
open override func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
@@ -54,12 +60,14 @@ open class RxInfiniteCollectionViewSectionedReloadDataSource<S: SectionModelType
|
||||
|
||||
open class RxInfiniteCollectionViewSectionedAnimatedDataSource<S: AnimatableSectionModelType>: RxCollectionViewSectionedAnimatedDataSource<S> {
|
||||
|
||||
public var isEnabled: Bool = true
|
||||
|
||||
open override subscript(section: Int) -> S {
|
||||
let section = InfiniteDataSources.section(from: section, numberOfSections: sectionModels.count)
|
||||
return self.sectionModels[section]
|
||||
}
|
||||
|
||||
open override subscript(indexPath: IndexPath) -> I {
|
||||
open override subscript(indexPath: IndexPath) -> Item {
|
||||
get {
|
||||
let indexPath = InfiniteDataSources.indexPath(from: indexPath,
|
||||
numberOfSections: sectionModels.count,
|
||||
@@ -77,7 +85,7 @@ open class RxInfiniteCollectionViewSectionedAnimatedDataSource<S: AnimatableSect
|
||||
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
|
||||
fatalError()
|
||||
}
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: layout.itemSize)
|
||||
return InfiniteDataSources.multiplier(estimatedItemSize: layout.itemSize, enabled: isEnabled)
|
||||
}
|
||||
|
||||
open override func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 572 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 688 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
Reference in New Issue
Block a user