├── .coveralls.yml
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .slather.yml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── CardStackView
├── Assets
│ └── .gitkeep
├── CardStackView.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── CardStackView.xcscheme
├── CardStackView
│ ├── CardStackView.h
│ └── Info.plist
└── Classes
│ ├── .gitkeep
│ ├── CardStackView.swift
│ ├── CardView.swift
│ └── PaginationView.swift
├── Example
├── CardStackView.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── swiftpm
│ │ │ └── Package.resolved
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── CardStackView_Example.xcscheme
│ │ └── CardStackView_Tests.xcscheme
├── CardStackView
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ └── ViewController.swift
├── Tests
│ ├── CardStackViewSpec.swift
│ ├── CardViewSpec.swift
│ ├── Info.plist
│ └── PaginationViewSpec.swift
└── example.gif
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── CardStackView
│ └── CardStackView.swift
└── Tests
├── CardStackViewTests
├── CardStackViewTests.swift
└── XCTestManifests.swift
└── LinuxMain.swift
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis
2 | repo_token: n6BtKpCveOrlYeoRz4eAM0XG3g0j6ZQAO
3 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: macOS-latest
9 | strategy:
10 | matrix:
11 | destination: ['platform=iOS Simulator,OS=14.0,name=iPhone 11']
12 |
13 | steps:
14 | - uses: actions/checkout@v1
15 | - name: xcode-select -switch /Applications/Xcode_12.app
16 | run: |
17 | xcode-select -print-path
18 | sudo xcode-select -switch /Applications/Xcode_12.app
19 | xcode-select -print-path
20 | - name: xcrun simctl list
21 | run: |
22 | xcrun simctl list
23 | - name: Build and run test
24 | run: |
25 | cd Example
26 | set -o pipefail
27 | xcodebuild clean test -project CardStackView.xcodeproj -scheme CardStackView_Example -destination 'platform=iOS Simulator,name=iPhone 11,OS=14.0' | xcpretty
28 | env:
29 | destination: ${{ matrix.destination }}
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | .build
6 | build/
7 | *.pbxuser
8 | !default.pbxuser
9 | *.mode1v3
10 | !default.mode1v3
11 | *.mode2v3
12 | !default.mode2v3
13 | *.perspectivev3
14 | !default.perspectivev3
15 | xcuserdata/
16 | *.xccheckout
17 | profile
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 |
23 | # Bundler
24 | .bundle
25 |
26 | Carthage
27 | # We recommend against adding the Pods directory to your .gitignore. However
28 | # you should judge for yourself, the pros and cons are mentioned at:
29 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
30 | #
31 | # Note: if you ignore the Pods directory, make sure to uncomment
32 | # `pod install` in .travis.yml
33 | #
34 | # Pods/
35 |
--------------------------------------------------------------------------------
/.slather.yml:
--------------------------------------------------------------------------------
1 | ci_service: travis_ci
2 | ci_access_token: n6BtKpCveOrlYeoRz4eAM0XG3g0j6ZQAO
3 | coverage_service: coveralls
4 | source_directory: CardStackView
5 | workspace: Example/CardStackView.xcworkspace
6 | scheme: CardStackView_Example
7 | ignore:
8 | - ProjectTests/*
9 | - Pods/*
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CardStackView/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gomfucius/CardStackView/941769f3435c9adcdca7b3236ca6e5cda7ae8d46/CardStackView/Assets/.gitkeep
--------------------------------------------------------------------------------
/CardStackView/CardStackView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3730714921A73DE800D64ACE /* CardStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3730714721A73DE800D64ACE /* CardStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | 3730715421A73E1D00D64ACE /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3730715021A73E1D00D64ACE /* CardView.swift */; };
12 | 3730715521A73E1D00D64ACE /* PaginationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3730715121A73E1D00D64ACE /* PaginationView.swift */; };
13 | 3730715721A73E1D00D64ACE /* CardStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3730715321A73E1D00D64ACE /* CardStackView.swift */; };
14 | /* End PBXBuildFile section */
15 |
16 | /* Begin PBXFileReference section */
17 | 3730714421A73DE800D64ACE /* CardStackView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CardStackView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
18 | 3730714721A73DE800D64ACE /* CardStackView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardStackView.h; sourceTree = ""; };
19 | 3730714821A73DE800D64ACE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
20 | 3730715021A73E1D00D64ACE /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; };
21 | 3730715121A73E1D00D64ACE /* PaginationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaginationView.swift; sourceTree = ""; };
22 | 3730715321A73E1D00D64ACE /* CardStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardStackView.swift; sourceTree = ""; };
23 | /* End PBXFileReference section */
24 |
25 | /* Begin PBXFrameworksBuildPhase section */
26 | 3730714121A73DE800D64ACE /* Frameworks */ = {
27 | isa = PBXFrameworksBuildPhase;
28 | buildActionMask = 2147483647;
29 | files = (
30 | );
31 | runOnlyForDeploymentPostprocessing = 0;
32 | };
33 | /* End PBXFrameworksBuildPhase section */
34 |
35 | /* Begin PBXGroup section */
36 | 3730713A21A73DE800D64ACE = {
37 | isa = PBXGroup;
38 | children = (
39 | 3730714621A73DE800D64ACE /* CardStackView */,
40 | 3730714521A73DE800D64ACE /* Products */,
41 | );
42 | sourceTree = "";
43 | };
44 | 3730714521A73DE800D64ACE /* Products */ = {
45 | isa = PBXGroup;
46 | children = (
47 | 3730714421A73DE800D64ACE /* CardStackView.framework */,
48 | );
49 | name = Products;
50 | sourceTree = "";
51 | };
52 | 3730714621A73DE800D64ACE /* CardStackView */ = {
53 | isa = PBXGroup;
54 | children = (
55 | 3730714F21A73E1D00D64ACE /* Classes */,
56 | 3730714721A73DE800D64ACE /* CardStackView.h */,
57 | 3730714821A73DE800D64ACE /* Info.plist */,
58 | );
59 | path = CardStackView;
60 | sourceTree = "";
61 | };
62 | 3730714F21A73E1D00D64ACE /* Classes */ = {
63 | isa = PBXGroup;
64 | children = (
65 | 3730715021A73E1D00D64ACE /* CardView.swift */,
66 | 3730715121A73E1D00D64ACE /* PaginationView.swift */,
67 | 3730715321A73E1D00D64ACE /* CardStackView.swift */,
68 | );
69 | path = Classes;
70 | sourceTree = SOURCE_ROOT;
71 | };
72 | /* End PBXGroup section */
73 |
74 | /* Begin PBXHeadersBuildPhase section */
75 | 3730713F21A73DE800D64ACE /* Headers */ = {
76 | isa = PBXHeadersBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | 3730714921A73DE800D64ACE /* CardStackView.h in Headers */,
80 | );
81 | runOnlyForDeploymentPostprocessing = 0;
82 | };
83 | /* End PBXHeadersBuildPhase section */
84 |
85 | /* Begin PBXNativeTarget section */
86 | 3730714321A73DE800D64ACE /* CardStackView */ = {
87 | isa = PBXNativeTarget;
88 | buildConfigurationList = 3730714C21A73DE800D64ACE /* Build configuration list for PBXNativeTarget "CardStackView" */;
89 | buildPhases = (
90 | 3730713F21A73DE800D64ACE /* Headers */,
91 | 3730714021A73DE800D64ACE /* Sources */,
92 | 3730714121A73DE800D64ACE /* Frameworks */,
93 | 3730714221A73DE800D64ACE /* Resources */,
94 | );
95 | buildRules = (
96 | );
97 | dependencies = (
98 | );
99 | name = CardStackView;
100 | productName = CardStackView;
101 | productReference = 3730714421A73DE800D64ACE /* CardStackView.framework */;
102 | productType = "com.apple.product-type.framework";
103 | };
104 | /* End PBXNativeTarget section */
105 |
106 | /* Begin PBXProject section */
107 | 3730713B21A73DE800D64ACE /* Project object */ = {
108 | isa = PBXProject;
109 | attributes = {
110 | LastUpgradeCheck = 1000;
111 | ORGANIZATIONNAME = "Genki Mine";
112 | TargetAttributes = {
113 | 3730714321A73DE800D64ACE = {
114 | CreatedOnToolsVersion = 10.0;
115 | };
116 | };
117 | };
118 | buildConfigurationList = 3730713E21A73DE800D64ACE /* Build configuration list for PBXProject "CardStackView" */;
119 | compatibilityVersion = "Xcode 9.3";
120 | developmentRegion = en;
121 | hasScannedForEncodings = 0;
122 | knownRegions = (
123 | en,
124 | );
125 | mainGroup = 3730713A21A73DE800D64ACE;
126 | productRefGroup = 3730714521A73DE800D64ACE /* Products */;
127 | projectDirPath = "";
128 | projectRoot = "";
129 | targets = (
130 | 3730714321A73DE800D64ACE /* CardStackView */,
131 | );
132 | };
133 | /* End PBXProject section */
134 |
135 | /* Begin PBXResourcesBuildPhase section */
136 | 3730714221A73DE800D64ACE /* Resources */ = {
137 | isa = PBXResourcesBuildPhase;
138 | buildActionMask = 2147483647;
139 | files = (
140 | );
141 | runOnlyForDeploymentPostprocessing = 0;
142 | };
143 | /* End PBXResourcesBuildPhase section */
144 |
145 | /* Begin PBXSourcesBuildPhase section */
146 | 3730714021A73DE800D64ACE /* Sources */ = {
147 | isa = PBXSourcesBuildPhase;
148 | buildActionMask = 2147483647;
149 | files = (
150 | 3730715721A73E1D00D64ACE /* CardStackView.swift in Sources */,
151 | 3730715521A73E1D00D64ACE /* PaginationView.swift in Sources */,
152 | 3730715421A73E1D00D64ACE /* CardView.swift in Sources */,
153 | );
154 | runOnlyForDeploymentPostprocessing = 0;
155 | };
156 | /* End PBXSourcesBuildPhase section */
157 |
158 | /* Begin XCBuildConfiguration section */
159 | 3730714A21A73DE800D64ACE /* Debug */ = {
160 | isa = XCBuildConfiguration;
161 | buildSettings = {
162 | ALWAYS_SEARCH_USER_PATHS = NO;
163 | CLANG_ANALYZER_NONNULL = YES;
164 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
165 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
166 | CLANG_CXX_LIBRARY = "libc++";
167 | CLANG_ENABLE_MODULES = YES;
168 | CLANG_ENABLE_OBJC_ARC = YES;
169 | CLANG_ENABLE_OBJC_WEAK = YES;
170 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
171 | CLANG_WARN_BOOL_CONVERSION = YES;
172 | CLANG_WARN_COMMA = YES;
173 | CLANG_WARN_CONSTANT_CONVERSION = YES;
174 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
175 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
176 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
177 | CLANG_WARN_EMPTY_BODY = YES;
178 | CLANG_WARN_ENUM_CONVERSION = YES;
179 | CLANG_WARN_INFINITE_RECURSION = YES;
180 | CLANG_WARN_INT_CONVERSION = YES;
181 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
182 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
183 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
184 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
185 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
186 | CLANG_WARN_STRICT_PROTOTYPES = YES;
187 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
188 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
189 | CLANG_WARN_UNREACHABLE_CODE = YES;
190 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
191 | CODE_SIGN_IDENTITY = "iPhone Developer";
192 | COPY_PHASE_STRIP = NO;
193 | CURRENT_PROJECT_VERSION = 1;
194 | DEBUG_INFORMATION_FORMAT = dwarf;
195 | ENABLE_STRICT_OBJC_MSGSEND = YES;
196 | ENABLE_TESTABILITY = YES;
197 | GCC_C_LANGUAGE_STANDARD = gnu11;
198 | GCC_DYNAMIC_NO_PIC = NO;
199 | GCC_NO_COMMON_BLOCKS = YES;
200 | GCC_OPTIMIZATION_LEVEL = 0;
201 | GCC_PREPROCESSOR_DEFINITIONS = (
202 | "DEBUG=1",
203 | "$(inherited)",
204 | );
205 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
206 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
207 | GCC_WARN_UNDECLARED_SELECTOR = YES;
208 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
209 | GCC_WARN_UNUSED_FUNCTION = YES;
210 | GCC_WARN_UNUSED_VARIABLE = YES;
211 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
212 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
213 | MTL_FAST_MATH = YES;
214 | ONLY_ACTIVE_ARCH = YES;
215 | SDKROOT = iphoneos;
216 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
217 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
218 | VERSIONING_SYSTEM = "apple-generic";
219 | VERSION_INFO_PREFIX = "";
220 | };
221 | name = Debug;
222 | };
223 | 3730714B21A73DE800D64ACE /* Release */ = {
224 | isa = XCBuildConfiguration;
225 | buildSettings = {
226 | ALWAYS_SEARCH_USER_PATHS = NO;
227 | CLANG_ANALYZER_NONNULL = YES;
228 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
230 | CLANG_CXX_LIBRARY = "libc++";
231 | CLANG_ENABLE_MODULES = YES;
232 | CLANG_ENABLE_OBJC_ARC = YES;
233 | CLANG_ENABLE_OBJC_WEAK = YES;
234 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
235 | CLANG_WARN_BOOL_CONVERSION = YES;
236 | CLANG_WARN_COMMA = YES;
237 | CLANG_WARN_CONSTANT_CONVERSION = YES;
238 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
239 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
240 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
241 | CLANG_WARN_EMPTY_BODY = YES;
242 | CLANG_WARN_ENUM_CONVERSION = YES;
243 | CLANG_WARN_INFINITE_RECURSION = YES;
244 | CLANG_WARN_INT_CONVERSION = YES;
245 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
246 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
247 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
248 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
249 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
250 | CLANG_WARN_STRICT_PROTOTYPES = YES;
251 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
252 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
253 | CLANG_WARN_UNREACHABLE_CODE = YES;
254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
255 | CODE_SIGN_IDENTITY = "iPhone Developer";
256 | COPY_PHASE_STRIP = NO;
257 | CURRENT_PROJECT_VERSION = 1;
258 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
259 | ENABLE_NS_ASSERTIONS = NO;
260 | ENABLE_STRICT_OBJC_MSGSEND = YES;
261 | GCC_C_LANGUAGE_STANDARD = gnu11;
262 | GCC_NO_COMMON_BLOCKS = YES;
263 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
264 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
265 | GCC_WARN_UNDECLARED_SELECTOR = YES;
266 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
267 | GCC_WARN_UNUSED_FUNCTION = YES;
268 | GCC_WARN_UNUSED_VARIABLE = YES;
269 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
270 | MTL_ENABLE_DEBUG_INFO = NO;
271 | MTL_FAST_MATH = YES;
272 | SDKROOT = iphoneos;
273 | SWIFT_COMPILATION_MODE = wholemodule;
274 | SWIFT_OPTIMIZATION_LEVEL = "-O";
275 | VALIDATE_PRODUCT = YES;
276 | VERSIONING_SYSTEM = "apple-generic";
277 | VERSION_INFO_PREFIX = "";
278 | };
279 | name = Release;
280 | };
281 | 3730714D21A73DE800D64ACE /* Debug */ = {
282 | isa = XCBuildConfiguration;
283 | buildSettings = {
284 | CODE_SIGN_IDENTITY = "";
285 | CODE_SIGN_STYLE = Automatic;
286 | DEFINES_MODULE = YES;
287 | DEVELOPMENT_TEAM = L5GKNB78UR;
288 | DYLIB_COMPATIBILITY_VERSION = 1;
289 | DYLIB_CURRENT_VERSION = 1;
290 | DYLIB_INSTALL_NAME_BASE = "@rpath";
291 | INFOPLIST_FILE = CardStackView/Info.plist;
292 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
293 | LD_RUNPATH_SEARCH_PATHS = (
294 | "$(inherited)",
295 | "@executable_path/Frameworks",
296 | "@loader_path/Frameworks",
297 | );
298 | PRODUCT_BUNDLE_IDENTIFIER = com.summitisland.CardStackView;
299 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
300 | SKIP_INSTALL = YES;
301 | SWIFT_VERSION = 4.2;
302 | TARGETED_DEVICE_FAMILY = "1,2";
303 | };
304 | name = Debug;
305 | };
306 | 3730714E21A73DE800D64ACE /* Release */ = {
307 | isa = XCBuildConfiguration;
308 | buildSettings = {
309 | CODE_SIGN_IDENTITY = "";
310 | CODE_SIGN_STYLE = Automatic;
311 | DEFINES_MODULE = YES;
312 | DEVELOPMENT_TEAM = L5GKNB78UR;
313 | DYLIB_COMPATIBILITY_VERSION = 1;
314 | DYLIB_CURRENT_VERSION = 1;
315 | DYLIB_INSTALL_NAME_BASE = "@rpath";
316 | INFOPLIST_FILE = CardStackView/Info.plist;
317 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
318 | LD_RUNPATH_SEARCH_PATHS = (
319 | "$(inherited)",
320 | "@executable_path/Frameworks",
321 | "@loader_path/Frameworks",
322 | );
323 | PRODUCT_BUNDLE_IDENTIFIER = com.summitisland.CardStackView;
324 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
325 | SKIP_INSTALL = YES;
326 | SWIFT_VERSION = 4.2;
327 | TARGETED_DEVICE_FAMILY = "1,2";
328 | };
329 | name = Release;
330 | };
331 | /* End XCBuildConfiguration section */
332 |
333 | /* Begin XCConfigurationList section */
334 | 3730713E21A73DE800D64ACE /* Build configuration list for PBXProject "CardStackView" */ = {
335 | isa = XCConfigurationList;
336 | buildConfigurations = (
337 | 3730714A21A73DE800D64ACE /* Debug */,
338 | 3730714B21A73DE800D64ACE /* Release */,
339 | );
340 | defaultConfigurationIsVisible = 0;
341 | defaultConfigurationName = Release;
342 | };
343 | 3730714C21A73DE800D64ACE /* Build configuration list for PBXNativeTarget "CardStackView" */ = {
344 | isa = XCConfigurationList;
345 | buildConfigurations = (
346 | 3730714D21A73DE800D64ACE /* Debug */,
347 | 3730714E21A73DE800D64ACE /* Release */,
348 | );
349 | defaultConfigurationIsVisible = 0;
350 | defaultConfigurationName = Release;
351 | };
352 | /* End XCConfigurationList section */
353 | };
354 | rootObject = 3730713B21A73DE800D64ACE /* Project object */;
355 | }
356 |
--------------------------------------------------------------------------------
/CardStackView/CardStackView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CardStackView/CardStackView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CardStackView/CardStackView.xcodeproj/xcshareddata/xcschemes/CardStackView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/CardStackView/CardStackView/CardStackView.h:
--------------------------------------------------------------------------------
1 | //
2 | // CardStackView.h
3 | // CardStackView
4 | //
5 | // Created by Genki Mine on 11/22/18.
6 | // Copyright © 2018 Genki Mine. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for CardStackView.
12 | FOUNDATION_EXPORT double CardStackViewVersionNumber;
13 |
14 | //! Project version string for CardStackView.
15 | FOUNDATION_EXPORT const unsigned char CardStackViewVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/CardStackView/CardStackView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CardStackView/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gomfucius/CardStackView/941769f3435c9adcdca7b3236ca6e5cda7ae8d46/CardStackView/Classes/.gitkeep
--------------------------------------------------------------------------------
/CardStackView/Classes/CardStackView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardStackView.swift
3 | // CardStackView
4 | //
5 | // Created by Genki Mine on 7/9/17.
6 | // Copyright © 2017 Genki. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | protocol CardStackViewDelegate: class {
13 | func cardStackViewDidChangePage(_ cardStackView: CardStackView)
14 | }
15 |
16 | open class CardStackView: UIView {
17 |
18 | class Constants {
19 | static let throwingThreshold: Float = 500.0
20 | }
21 |
22 | weak var delegate: CardStackViewDelegate?
23 |
24 | var cardViews = [CardView]()
25 | var panGesture: UIPanGestureRecognizer!
26 | var currentOffest: UIOffset!
27 | var beganPoint: CGPoint?
28 | var currentCard: CardView?
29 | var paginationView: PaginationView?
30 | var throwDuration: TimeInterval!
31 |
32 | /// Used to protected from swiping while the first card is out of the screen which causes weird animation issues
33 | var panEnabled = true
34 |
35 | private(set) var currentIndex: Int = 0
36 |
37 | // MARK: - Init
38 |
39 | public init(cards: [UIView], showsPagination: Bool = true, maxAngle: Int = 10, randomAngle: Bool = true, throwDuration: TimeInterval = 0.3) {
40 | super.init(frame: CGRect.zero)
41 |
42 | if cards.count == 0 {
43 | return
44 | }
45 |
46 | self.throwDuration = throwDuration
47 |
48 | if showsPagination {
49 | addPagination(withCount: cards.count)
50 | }
51 |
52 | // Add views
53 | for index in 0...cards.count - 1 {
54 | let i = cards.count / 2 - index
55 |
56 | let randomInt = Int(arc4random_uniform(UInt32(maxAngle)))
57 | let stuff = -1 * maxAngle / 2 + randomInt
58 | let angle = randomAngle ? CGFloat(stuff) : CGFloat((i * 2) % maxAngle)
59 | let cardView = CardView(view: cards[index], angle: angle)
60 | cardViews.append(cardView)
61 | self.addSubview(cardView)
62 |
63 | // Autolayout
64 | cardView.translatesAutoresizingMaskIntoConstraints = false
65 | let views = ["cardView": cardView]
66 | let paginationBottomMargin = showsPagination ? 30 : 0
67 | let metrics = ["paginationBottomMargin": paginationBottomMargin]
68 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[cardView]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: metrics, views: views))
69 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[cardView]-(paginationBottomMargin)-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: metrics, views: views))
70 | }
71 |
72 | // Add pan gestures
73 | self.panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(gesture:)))
74 | self.panGesture.delegate = self
75 | self.addGestureRecognizer(self.panGesture!)
76 | }
77 |
78 | override init(frame: CGRect) {
79 | super.init(frame: frame)
80 | }
81 |
82 | required public init?(coder aDecoder: NSCoder) {
83 | super.init(coder: aDecoder)
84 | }
85 |
86 | // MARK: - CardStackView
87 |
88 | func addPagination(withCount count: Int) {
89 | paginationView = PaginationView(pages: count)
90 | guard let paginationView = paginationView else {
91 | return
92 | }
93 | self.addSubview(paginationView)
94 | paginationView.translatesAutoresizingMaskIntoConstraints = false
95 | let views = ["paginationView": paginationView]
96 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[paginationView]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
97 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:[paginationView(10)]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
98 | }
99 |
100 | func swipeCard(_ card: CardView, direction: CardView.Direction, velocity: CGPoint) {
101 | // Throw card off the screen
102 | UIView.animate(withDuration: throwDuration, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 5.0, options: .curveEaseOut, animations: {
103 | let screenWidth = UIScreen.main.bounds.width
104 | let directionMultiplier: CGFloat = direction == .left ? -1 : 1
105 | card.center = CGPoint(x: directionMultiplier * (screenWidth + card.bounds.width / 2), y: card.center.y + (velocity.y - card.center.y) / 6)
106 | }) { _ in
107 | // Snap back the card back to center
108 | self.panEnabled = true
109 |
110 | if direction == .left {
111 | self.bringSubviewToFront(card)
112 | self.currentIndex -= 1
113 | } else {
114 | self.sendSubviewToBack(card)
115 | self.currentIndex += 1
116 | }
117 |
118 | if self.currentIndex < 0 {
119 | self.currentIndex = self.cardViews.count - 1
120 | } else if self.currentIndex >= self.cardViews.count {
121 | self.currentIndex = 0
122 | }
123 |
124 | if let paginationView = self.paginationView {
125 | self.sendSubviewToBack(paginationView)
126 | }
127 |
128 | UIView.animate(withDuration: self.throwDuration, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 5.0, options: .curveEaseOut, animations: {
129 | card.center = self.convert(card.center, to: card)
130 | card.resetPositionAndRotation(withElasticity: false)
131 | }, completion: { _ in
132 | self.didFinishSwipingCardTo(direction: direction)
133 | })
134 |
135 | self.delegate?.cardStackViewDidChangePage(self)
136 | }
137 | }
138 |
139 | func didFinishSwipingCardTo(direction: CardView.Direction) {
140 | paginationView?.incrementPage(by: direction == .left ? -1 : 1)
141 | }
142 | }
143 |
144 | // MARK: - UIGestureRecognizerDelegate
145 |
146 | extension CardStackView: UIGestureRecognizerDelegate {
147 |
148 | @objc func handlePanGesture(gesture: UIPanGestureRecognizer) {
149 | if !panEnabled {
150 | return
151 | }
152 |
153 | switch gesture.state {
154 | case .began:
155 | beganPoint = gesture.location(in: self)
156 | break
157 | case .ended:
158 | if let currentCard = currentCard {
159 | let velocity = gesture.velocity(in: self)
160 | let magnitude = sqrtf(Float((velocity.x * velocity.x) + (velocity.y * velocity.y)))
161 |
162 | // If there was enough flick, throw card and rearrange z position
163 | if magnitude > Constants.throwingThreshold {
164 | let direction: CardView.Direction = velocity.x < 0 ? .left : .right
165 |
166 | // If throwing direction is not the same as initial dragging direction, reset the card to original position
167 | if (direction == .left && currentCard != cardViews.first)
168 | || (direction == .right && currentCard != cardViews.last) {
169 | panEnabled = true
170 | currentCard.resetPositionAndRotation(withElasticity: true)
171 | } else {
172 | // Can throw
173 | if direction == .left {
174 | cardViews = cardViews.rearrange(fromIndex: 0, toIndex: cardViews.count - 1)
175 | } else {
176 | cardViews = cardViews.rearrange(fromIndex: cardViews.count - 1, toIndex: 0)
177 | }
178 | swipeCard(currentCard, direction: direction, velocity: velocity)
179 | panEnabled = false
180 | }
181 |
182 | } else {
183 | panEnabled = true
184 | currentCard.resetPositionAndRotation(withElasticity: true)
185 | }
186 | }
187 | currentCard = nil
188 | break
189 | default:
190 | let gesturePoint = gesture.location(in: self)
191 |
192 | // Determine if card is going left or right
193 | if currentCard == nil, let beganPoint = beganPoint {
194 | if gesturePoint.x < beganPoint.x {
195 | currentCard = cardViews.first
196 | } else {
197 | currentCard = cardViews.last
198 | }
199 |
200 | guard let currentCard = currentCard else {
201 | return
202 | }
203 | let boxLocation = gesture.location(in: currentCard)
204 | currentOffest = UIOffset(horizontal: boxLocation.x - currentCard.bounds.midX, vertical: boxLocation.y - currentCard.bounds.midY)
205 | UIView.animate(withDuration: 0.1) {
206 | // Rotate card back to straight
207 | currentCard.transform = .identity
208 | }
209 | }
210 |
211 | // Move current card with finger drag
212 | currentCard?.center = CGPoint(x: gesturePoint.x - currentOffest.horizontal, y: gesturePoint.y - currentOffest.vertical)
213 | break
214 | }
215 | }
216 | }
217 |
218 | // MARK: - Array
219 |
220 | extension Array {
221 | mutating func rearrange(fromIndex: Int, toIndex: Int) -> Array {
222 | let element = self.remove(at: fromIndex)
223 | self.insert(element, at: toIndex)
224 | return self
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/CardStackView/Classes/CardView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardView.swift
3 | // CardStackView
4 | //
5 | // Created by Genki Mine on 7/9/17.
6 | // Copyright © 2017 Genki. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | var count = 0
13 |
14 | open class CardView: UIView, UIGestureRecognizerDelegate {
15 |
16 | enum Direction: Int {
17 | case left
18 | case right
19 | }
20 |
21 | var originalAngle: CGFloat!
22 | var originalBounds: CGRect!
23 | var originalCenter: CGPoint!
24 |
25 | convenience init(view: UIView, angle: CGFloat) {
26 | self.init(frame: CGRect.zero)
27 |
28 | originalAngle = angle
29 |
30 | self.addSubview(view)
31 |
32 | self.transform = CGAffineTransform(rotationAngle: CGFloat(angle * CGFloat(Double.pi) / 180))
33 |
34 | view.translatesAutoresizingMaskIntoConstraints = false
35 | let views = ["view": view]
36 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[view]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
37 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
38 | }
39 |
40 | override init(frame: CGRect) {
41 | super.init(frame: frame)
42 | }
43 |
44 | required public init?(coder aDecoder: NSCoder) {
45 | super.init(coder: aDecoder)
46 | }
47 |
48 | override open func layoutSubviews() {
49 | super.layoutSubviews()
50 |
51 | if originalBounds == nil {
52 | originalBounds = self.bounds
53 | originalCenter = self.center
54 | }
55 | }
56 |
57 | func resetPositionAndRotation(withElasticity: Bool) {
58 | if withElasticity {
59 | var spring: CGFloat = 0.0
60 | var velocity: CGFloat = 0.0
61 | spring = 0.7
62 | velocity = 15.0
63 |
64 | UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: spring, initialSpringVelocity: velocity, options: .curveEaseOut, animations: {
65 | self.bounds = self.originalBounds
66 | self.center = self.originalCenter
67 | self.transform = CGAffineTransform(rotationAngle: CGFloat(self.originalAngle * CGFloat(Double.pi) / 180))
68 | }, completion: nil)
69 | } else {
70 | UIView.animate(withDuration: 0.3) {
71 | self.bounds = self.originalBounds
72 | self.center = self.originalCenter
73 | self.transform = CGAffineTransform(rotationAngle: CGFloat(self.originalAngle * CGFloat(Double.pi) / 180))
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/CardStackView/Classes/PaginationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PaginationView.swift
3 | // CardStackView
4 | //
5 | // Created by Genki Mine on 7/22/17.
6 | // Copyright © 2017 Genki. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | open class PaginationView: UIView {
12 |
13 | var currentIndex = 0
14 | var maxIndex = 0
15 | var dots = [UIView]()
16 |
17 | class Constants {
18 | static let dotSize: CGFloat = 8.0
19 | static let dotSpacing: CGFloat = 10.0
20 | static let selectedColor = UIColor(red: 60.0 / 255.0, green: 184.0 / 255.0, blue: 120.0 / 255.0, alpha: 1.0)
21 | static let unselectedColor = UIColor.lightGray
22 | }
23 |
24 | // MARK: - Init
25 |
26 | init(pages: Int, frame: CGRect = CGRect.zero) {
27 | super.init(frame: CGRect.zero)
28 | maxIndex = pages - 1
29 | makeDots(withCount: pages)
30 | changePage(to: 0)
31 | }
32 |
33 | public override init(frame: CGRect) {
34 | super.init(frame: frame)
35 | fatalError("init(frame: unavailable. Use init(pages: Int, frame: CGRect) instead.")
36 | }
37 |
38 | required public init?(coder aDecoder: NSCoder) {
39 | super.init(coder: aDecoder)
40 | }
41 |
42 | // MARK: - PaginationView
43 |
44 | func makeDots(withCount count: Int) {
45 | for index in 0...count - 1 {
46 | let dot = UIView()
47 | dot.layer.cornerRadius = Constants.dotSize / 2
48 | dot.backgroundColor = Constants.unselectedColor
49 | self.addSubview(dot)
50 | dot.translatesAutoresizingMaskIntoConstraints = false
51 | let views = ["dot": dot]
52 | let metrics = ["dotSize": Constants.dotSize]
53 | let positionX = CGFloat(count / 2 - count + index + 1)
54 | let sizeAndSpacing = Constants.dotSize + Constants.dotSpacing
55 | NSLayoutConstraint(item: dot, attribute: .centerX, relatedBy: .equal, toItem: dot.superview, attribute: .centerX, multiplier: 1.0, constant: sizeAndSpacing * positionX).isActive = true
56 | NSLayoutConstraint(item: dot, attribute: .centerY, relatedBy: .equal, toItem: dot.superview, attribute: .centerY, multiplier: 1.0, constant: 0.0).isActive = true
57 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "[dot(dotSize)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: metrics, views: views))
58 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:[dot(dotSize)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: metrics, views: views))
59 | dots.append(dot)
60 | }
61 | }
62 |
63 | func incrementPage(by number: Int) {
64 | changePage(to: currentIndex + number)
65 | }
66 |
67 | func changePage(to page: Int) {
68 | dots[currentIndex].backgroundColor = Constants.unselectedColor
69 |
70 | if page > maxIndex {
71 | currentIndex = 0
72 | } else if page < 0 {
73 | currentIndex = maxIndex
74 | } else {
75 | currentIndex = page
76 | }
77 |
78 | dots[currentIndex].backgroundColor = Constants.selectedColor
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 373FBCB71F251D080017BBDC /* CardStackViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373FBCB61F251D080017BBDC /* CardStackViewSpec.swift */; };
11 | 373FBCB91F2523890017BBDC /* PaginationViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373FBCB81F2523890017BBDC /* PaginationViewSpec.swift */; };
12 | 373FBCBB1F2525670017BBDC /* CardViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373FBCBA1F2525670017BBDC /* CardViewSpec.swift */; };
13 | 41E8A259255623EC009DF7C9 /* Quick in Frameworks */ = {isa = PBXBuildFile; productRef = 41E8A258255623EC009DF7C9 /* Quick */; };
14 | 41E8A25D255623F5009DF7C9 /* Nimble in Frameworks */ = {isa = PBXBuildFile; productRef = 41E8A25C255623F5009DF7C9 /* Nimble */; };
15 | 41E8A27825563678009DF7C9 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27425563678009DF7C9 /* CardView.swift */; };
16 | 41E8A27925563678009DF7C9 /* PaginationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27525563678009DF7C9 /* PaginationView.swift */; };
17 | 41E8A27B25563678009DF7C9 /* CardStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27725563678009DF7C9 /* CardStackView.swift */; };
18 | 41E8A28025564585009DF7C9 /* CardStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27725563678009DF7C9 /* CardStackView.swift */; };
19 | 41E8A2832556458A009DF7C9 /* PaginationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27525563678009DF7C9 /* PaginationView.swift */; };
20 | 41E8A2862556458C009DF7C9 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E8A27425563678009DF7C9 /* CardView.swift */; };
21 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
22 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
23 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
24 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
25 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXContainerItemProxy section */
29 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
32 | proxyType = 1;
33 | remoteGlobalIDString = 607FACCF1AFB9204008FA782;
34 | remoteInfo = CardStackView;
35 | };
36 | /* End PBXContainerItemProxy section */
37 |
38 | /* Begin PBXFileReference section */
39 | 373FBCB61F251D080017BBDC /* CardStackViewSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardStackViewSpec.swift; sourceTree = ""; };
40 | 373FBCB81F2523890017BBDC /* PaginationViewSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaginationViewSpec.swift; sourceTree = ""; };
41 | 373FBCBA1F2525670017BBDC /* CardViewSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardViewSpec.swift; sourceTree = ""; };
42 | 41E8A27425563678009DF7C9 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; };
43 | 41E8A27525563678009DF7C9 /* PaginationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaginationView.swift; sourceTree = ""; };
44 | 41E8A27725563678009DF7C9 /* CardStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardStackView.swift; sourceTree = ""; };
45 | 607FACD01AFB9204008FA782 /* CardStackView_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CardStackView_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
48 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
49 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
50 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
51 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
52 | 607FACE51AFB9204008FA782 /* CardStackView_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CardStackView_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
54 | /* End PBXFileReference section */
55 |
56 | /* Begin PBXFrameworksBuildPhase section */
57 | 607FACCD1AFB9204008FA782 /* Frameworks */ = {
58 | isa = PBXFrameworksBuildPhase;
59 | buildActionMask = 2147483647;
60 | files = (
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | 607FACE21AFB9204008FA782 /* Frameworks */ = {
65 | isa = PBXFrameworksBuildPhase;
66 | buildActionMask = 2147483647;
67 | files = (
68 | 41E8A259255623EC009DF7C9 /* Quick in Frameworks */,
69 | 41E8A25D255623F5009DF7C9 /* Nimble in Frameworks */,
70 | );
71 | runOnlyForDeploymentPostprocessing = 0;
72 | };
73 | /* End PBXFrameworksBuildPhase section */
74 |
75 | /* Begin PBXGroup section */
76 | 41E8A257255623EC009DF7C9 /* Frameworks */ = {
77 | isa = PBXGroup;
78 | children = (
79 | );
80 | name = Frameworks;
81 | sourceTree = "";
82 | };
83 | 41E8A27325563678009DF7C9 /* Classes */ = {
84 | isa = PBXGroup;
85 | children = (
86 | 41E8A27425563678009DF7C9 /* CardView.swift */,
87 | 41E8A27525563678009DF7C9 /* PaginationView.swift */,
88 | 41E8A27725563678009DF7C9 /* CardStackView.swift */,
89 | );
90 | name = Classes;
91 | path = ../CardStackView/Classes;
92 | sourceTree = "";
93 | };
94 | 607FACC71AFB9204008FA782 = {
95 | isa = PBXGroup;
96 | children = (
97 | 41E8A27325563678009DF7C9 /* Classes */,
98 | 607FACD21AFB9204008FA782 /* Example for CardStackView */,
99 | 607FACE81AFB9204008FA782 /* Tests */,
100 | 607FACD11AFB9204008FA782 /* Products */,
101 | 41E8A257255623EC009DF7C9 /* Frameworks */,
102 | );
103 | sourceTree = "";
104 | };
105 | 607FACD11AFB9204008FA782 /* Products */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 607FACD01AFB9204008FA782 /* CardStackView_Example.app */,
109 | 607FACE51AFB9204008FA782 /* CardStackView_Tests.xctest */,
110 | );
111 | name = Products;
112 | sourceTree = "";
113 | };
114 | 607FACD21AFB9204008FA782 /* Example for CardStackView */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */,
118 | 607FACD71AFB9204008FA782 /* ViewController.swift */,
119 | 607FACD91AFB9204008FA782 /* Main.storyboard */,
120 | 607FACDC1AFB9204008FA782 /* Images.xcassets */,
121 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
122 | 607FACD31AFB9204008FA782 /* Supporting Files */,
123 | );
124 | name = "Example for CardStackView";
125 | path = CardStackView;
126 | sourceTree = "";
127 | };
128 | 607FACD31AFB9204008FA782 /* Supporting Files */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 607FACD41AFB9204008FA782 /* Info.plist */,
132 | );
133 | name = "Supporting Files";
134 | sourceTree = "";
135 | };
136 | 607FACE81AFB9204008FA782 /* Tests */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 373FBCB61F251D080017BBDC /* CardStackViewSpec.swift */,
140 | 373FBCBA1F2525670017BBDC /* CardViewSpec.swift */,
141 | 373FBCB81F2523890017BBDC /* PaginationViewSpec.swift */,
142 | 607FACE91AFB9204008FA782 /* Supporting Files */,
143 | );
144 | path = Tests;
145 | sourceTree = "";
146 | };
147 | 607FACE91AFB9204008FA782 /* Supporting Files */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 607FACEA1AFB9204008FA782 /* Info.plist */,
151 | );
152 | name = "Supporting Files";
153 | sourceTree = "";
154 | };
155 | /* End PBXGroup section */
156 |
157 | /* Begin PBXNativeTarget section */
158 | 607FACCF1AFB9204008FA782 /* CardStackView_Example */ = {
159 | isa = PBXNativeTarget;
160 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "CardStackView_Example" */;
161 | buildPhases = (
162 | 607FACCC1AFB9204008FA782 /* Sources */,
163 | 607FACCD1AFB9204008FA782 /* Frameworks */,
164 | 607FACCE1AFB9204008FA782 /* Resources */,
165 | );
166 | buildRules = (
167 | );
168 | dependencies = (
169 | );
170 | name = CardStackView_Example;
171 | packageProductDependencies = (
172 | );
173 | productName = CardStackView;
174 | productReference = 607FACD01AFB9204008FA782 /* CardStackView_Example.app */;
175 | productType = "com.apple.product-type.application";
176 | };
177 | 607FACE41AFB9204008FA782 /* CardStackView_Tests */ = {
178 | isa = PBXNativeTarget;
179 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "CardStackView_Tests" */;
180 | buildPhases = (
181 | 607FACE11AFB9204008FA782 /* Sources */,
182 | 607FACE21AFB9204008FA782 /* Frameworks */,
183 | 607FACE31AFB9204008FA782 /* Resources */,
184 | );
185 | buildRules = (
186 | );
187 | dependencies = (
188 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */,
189 | );
190 | name = CardStackView_Tests;
191 | packageProductDependencies = (
192 | 41E8A258255623EC009DF7C9 /* Quick */,
193 | 41E8A25C255623F5009DF7C9 /* Nimble */,
194 | );
195 | productName = Tests;
196 | productReference = 607FACE51AFB9204008FA782 /* CardStackView_Tests.xctest */;
197 | productType = "com.apple.product-type.bundle.unit-test";
198 | };
199 | /* End PBXNativeTarget section */
200 |
201 | /* Begin PBXProject section */
202 | 607FACC81AFB9204008FA782 /* Project object */ = {
203 | isa = PBXProject;
204 | attributes = {
205 | LastSwiftUpdateCheck = 0720;
206 | LastUpgradeCheck = 1200;
207 | ORGANIZATIONNAME = CocoaPods;
208 | TargetAttributes = {
209 | 607FACCF1AFB9204008FA782 = {
210 | CreatedOnToolsVersion = 6.3.1;
211 | LastSwiftMigration = 0820;
212 | };
213 | 607FACE41AFB9204008FA782 = {
214 | CreatedOnToolsVersion = 6.3.1;
215 | LastSwiftMigration = 0830;
216 | TestTargetID = 607FACCF1AFB9204008FA782;
217 | };
218 | };
219 | };
220 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "CardStackView" */;
221 | compatibilityVersion = "Xcode 3.2";
222 | developmentRegion = en;
223 | hasScannedForEncodings = 0;
224 | knownRegions = (
225 | en,
226 | Base,
227 | );
228 | mainGroup = 607FACC71AFB9204008FA782;
229 | packageReferences = (
230 | 4155ECDC254E6F5F00DBDB09 /* XCRemoteSwiftPackageReference "Nimble" */,
231 | 4155ECDF254E6FFB00DBDB09 /* XCRemoteSwiftPackageReference "Quick" */,
232 | );
233 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
234 | projectDirPath = "";
235 | projectRoot = "";
236 | targets = (
237 | 607FACCF1AFB9204008FA782 /* CardStackView_Example */,
238 | 607FACE41AFB9204008FA782 /* CardStackView_Tests */,
239 | );
240 | };
241 | /* End PBXProject section */
242 |
243 | /* Begin PBXResourcesBuildPhase section */
244 | 607FACCE1AFB9204008FA782 /* Resources */ = {
245 | isa = PBXResourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
249 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
250 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */,
251 | );
252 | runOnlyForDeploymentPostprocessing = 0;
253 | };
254 | 607FACE31AFB9204008FA782 /* Resources */ = {
255 | isa = PBXResourcesBuildPhase;
256 | buildActionMask = 2147483647;
257 | files = (
258 | );
259 | runOnlyForDeploymentPostprocessing = 0;
260 | };
261 | /* End PBXResourcesBuildPhase section */
262 |
263 | /* Begin PBXSourcesBuildPhase section */
264 | 607FACCC1AFB9204008FA782 /* Sources */ = {
265 | isa = PBXSourcesBuildPhase;
266 | buildActionMask = 2147483647;
267 | files = (
268 | 41E8A27B25563678009DF7C9 /* CardStackView.swift in Sources */,
269 | 41E8A27925563678009DF7C9 /* PaginationView.swift in Sources */,
270 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
271 | 41E8A27825563678009DF7C9 /* CardView.swift in Sources */,
272 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
273 | );
274 | runOnlyForDeploymentPostprocessing = 0;
275 | };
276 | 607FACE11AFB9204008FA782 /* Sources */ = {
277 | isa = PBXSourcesBuildPhase;
278 | buildActionMask = 2147483647;
279 | files = (
280 | 373FBCBB1F2525670017BBDC /* CardViewSpec.swift in Sources */,
281 | 41E8A28025564585009DF7C9 /* CardStackView.swift in Sources */,
282 | 373FBCB71F251D080017BBDC /* CardStackViewSpec.swift in Sources */,
283 | 41E8A2832556458A009DF7C9 /* PaginationView.swift in Sources */,
284 | 41E8A2862556458C009DF7C9 /* CardView.swift in Sources */,
285 | 373FBCB91F2523890017BBDC /* PaginationViewSpec.swift in Sources */,
286 | );
287 | runOnlyForDeploymentPostprocessing = 0;
288 | };
289 | /* End PBXSourcesBuildPhase section */
290 |
291 | /* Begin PBXTargetDependency section */
292 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
293 | isa = PBXTargetDependency;
294 | target = 607FACCF1AFB9204008FA782 /* CardStackView_Example */;
295 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
296 | };
297 | /* End PBXTargetDependency section */
298 |
299 | /* Begin PBXVariantGroup section */
300 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = {
301 | isa = PBXVariantGroup;
302 | children = (
303 | 607FACDA1AFB9204008FA782 /* Base */,
304 | );
305 | name = Main.storyboard;
306 | sourceTree = "";
307 | };
308 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
309 | isa = PBXVariantGroup;
310 | children = (
311 | 607FACDF1AFB9204008FA782 /* Base */,
312 | );
313 | name = LaunchScreen.xib;
314 | sourceTree = "";
315 | };
316 | /* End PBXVariantGroup section */
317 |
318 | /* Begin XCBuildConfiguration section */
319 | 607FACED1AFB9204008FA782 /* Debug */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ALWAYS_SEARCH_USER_PATHS = NO;
323 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
325 | CLANG_CXX_LIBRARY = "libc++";
326 | CLANG_ENABLE_MODULES = YES;
327 | CLANG_ENABLE_OBJC_ARC = YES;
328 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
329 | CLANG_WARN_BOOL_CONVERSION = YES;
330 | CLANG_WARN_COMMA = YES;
331 | CLANG_WARN_CONSTANT_CONVERSION = YES;
332 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
334 | CLANG_WARN_EMPTY_BODY = YES;
335 | CLANG_WARN_ENUM_CONVERSION = YES;
336 | CLANG_WARN_INFINITE_RECURSION = YES;
337 | CLANG_WARN_INT_CONVERSION = YES;
338 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
339 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
340 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
342 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
344 | CLANG_WARN_STRICT_PROTOTYPES = YES;
345 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
346 | CLANG_WARN_UNREACHABLE_CODE = YES;
347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
349 | COPY_PHASE_STRIP = NO;
350 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
351 | ENABLE_STRICT_OBJC_MSGSEND = YES;
352 | ENABLE_TESTABILITY = YES;
353 | GCC_C_LANGUAGE_STANDARD = gnu99;
354 | GCC_DYNAMIC_NO_PIC = NO;
355 | GCC_NO_COMMON_BLOCKS = YES;
356 | GCC_OPTIMIZATION_LEVEL = 0;
357 | GCC_PREPROCESSOR_DEFINITIONS = (
358 | "DEBUG=1",
359 | "$(inherited)",
360 | );
361 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
364 | GCC_WARN_UNDECLARED_SELECTOR = YES;
365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
366 | GCC_WARN_UNUSED_FUNCTION = YES;
367 | GCC_WARN_UNUSED_VARIABLE = YES;
368 | GENERATE_PROFILING_CODE = YES;
369 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
370 | MTL_ENABLE_DEBUG_INFO = YES;
371 | ONLY_ACTIVE_ARCH = YES;
372 | SDKROOT = iphoneos;
373 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
374 | };
375 | name = Debug;
376 | };
377 | 607FACEE1AFB9204008FA782 /* Release */ = {
378 | isa = XCBuildConfiguration;
379 | buildSettings = {
380 | ALWAYS_SEARCH_USER_PATHS = NO;
381 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
382 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
383 | CLANG_CXX_LIBRARY = "libc++";
384 | CLANG_ENABLE_MODULES = YES;
385 | CLANG_ENABLE_OBJC_ARC = YES;
386 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
387 | CLANG_WARN_BOOL_CONVERSION = YES;
388 | CLANG_WARN_COMMA = YES;
389 | CLANG_WARN_CONSTANT_CONVERSION = YES;
390 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
391 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
392 | CLANG_WARN_EMPTY_BODY = YES;
393 | CLANG_WARN_ENUM_CONVERSION = YES;
394 | CLANG_WARN_INFINITE_RECURSION = YES;
395 | CLANG_WARN_INT_CONVERSION = YES;
396 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
397 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
398 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
399 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
400 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
401 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
402 | CLANG_WARN_STRICT_PROTOTYPES = YES;
403 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
404 | CLANG_WARN_UNREACHABLE_CODE = YES;
405 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
406 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
407 | COPY_PHASE_STRIP = NO;
408 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
409 | ENABLE_NS_ASSERTIONS = NO;
410 | ENABLE_STRICT_OBJC_MSGSEND = YES;
411 | GCC_C_LANGUAGE_STANDARD = gnu99;
412 | GCC_NO_COMMON_BLOCKS = YES;
413 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
414 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
415 | GCC_WARN_UNDECLARED_SELECTOR = YES;
416 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
417 | GCC_WARN_UNUSED_FUNCTION = YES;
418 | GCC_WARN_UNUSED_VARIABLE = YES;
419 | GENERATE_PROFILING_CODE = YES;
420 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
421 | MTL_ENABLE_DEBUG_INFO = NO;
422 | SDKROOT = iphoneos;
423 | SWIFT_COMPILATION_MODE = wholemodule;
424 | SWIFT_OPTIMIZATION_LEVEL = "-O";
425 | VALIDATE_PRODUCT = YES;
426 | };
427 | name = Release;
428 | };
429 | 607FACF01AFB9204008FA782 /* Debug */ = {
430 | isa = XCBuildConfiguration;
431 | buildSettings = {
432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
433 | DEFINES_MODULE = NO;
434 | GENERATE_PROFILING_CODE = YES;
435 | INFOPLIST_FILE = CardStackView/Info.plist;
436 | LD_RUNPATH_SEARCH_PATHS = (
437 | "$(inherited)",
438 | "@executable_path/Frameworks",
439 | );
440 | MODULE_NAME = ExampleApp;
441 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
442 | PRODUCT_NAME = "$(TARGET_NAME)";
443 | SWIFT_VERSION = 4.2;
444 | };
445 | name = Debug;
446 | };
447 | 607FACF11AFB9204008FA782 /* Release */ = {
448 | isa = XCBuildConfiguration;
449 | buildSettings = {
450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
451 | DEFINES_MODULE = NO;
452 | GENERATE_PROFILING_CODE = YES;
453 | INFOPLIST_FILE = CardStackView/Info.plist;
454 | LD_RUNPATH_SEARCH_PATHS = (
455 | "$(inherited)",
456 | "@executable_path/Frameworks",
457 | );
458 | MODULE_NAME = ExampleApp;
459 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
460 | PRODUCT_NAME = "$(TARGET_NAME)";
461 | SWIFT_VERSION = 4.2;
462 | };
463 | name = Release;
464 | };
465 | 607FACF31AFB9204008FA782 /* Debug */ = {
466 | isa = XCBuildConfiguration;
467 | buildSettings = {
468 | CLANG_ENABLE_MODULES = YES;
469 | FRAMEWORK_SEARCH_PATHS = (
470 | "$(SDKROOT)/Developer/Library/Frameworks",
471 | "$(inherited)",
472 | );
473 | GCC_PREPROCESSOR_DEFINITIONS = (
474 | "DEBUG=1",
475 | "$(inherited)",
476 | );
477 | GENERATE_PROFILING_CODE = YES;
478 | INFOPLIST_FILE = Tests/Info.plist;
479 | LD_RUNPATH_SEARCH_PATHS = (
480 | "$(inherited)",
481 | "@executable_path/Frameworks",
482 | "@loader_path/Frameworks",
483 | );
484 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
485 | PRODUCT_NAME = "$(TARGET_NAME)";
486 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
487 | SWIFT_VERSION = 4.2;
488 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CardStackView_Example.app/CardStackView_Example";
489 | };
490 | name = Debug;
491 | };
492 | 607FACF41AFB9204008FA782 /* Release */ = {
493 | isa = XCBuildConfiguration;
494 | buildSettings = {
495 | CLANG_ENABLE_MODULES = YES;
496 | FRAMEWORK_SEARCH_PATHS = (
497 | "$(SDKROOT)/Developer/Library/Frameworks",
498 | "$(inherited)",
499 | );
500 | GENERATE_PROFILING_CODE = YES;
501 | INFOPLIST_FILE = Tests/Info.plist;
502 | LD_RUNPATH_SEARCH_PATHS = (
503 | "$(inherited)",
504 | "@executable_path/Frameworks",
505 | "@loader_path/Frameworks",
506 | );
507 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
508 | PRODUCT_NAME = "$(TARGET_NAME)";
509 | SWIFT_VERSION = 4.2;
510 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CardStackView_Example.app/CardStackView_Example";
511 | };
512 | name = Release;
513 | };
514 | /* End XCBuildConfiguration section */
515 |
516 | /* Begin XCConfigurationList section */
517 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "CardStackView" */ = {
518 | isa = XCConfigurationList;
519 | buildConfigurations = (
520 | 607FACED1AFB9204008FA782 /* Debug */,
521 | 607FACEE1AFB9204008FA782 /* Release */,
522 | );
523 | defaultConfigurationIsVisible = 0;
524 | defaultConfigurationName = Release;
525 | };
526 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "CardStackView_Example" */ = {
527 | isa = XCConfigurationList;
528 | buildConfigurations = (
529 | 607FACF01AFB9204008FA782 /* Debug */,
530 | 607FACF11AFB9204008FA782 /* Release */,
531 | );
532 | defaultConfigurationIsVisible = 0;
533 | defaultConfigurationName = Release;
534 | };
535 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "CardStackView_Tests" */ = {
536 | isa = XCConfigurationList;
537 | buildConfigurations = (
538 | 607FACF31AFB9204008FA782 /* Debug */,
539 | 607FACF41AFB9204008FA782 /* Release */,
540 | );
541 | defaultConfigurationIsVisible = 0;
542 | defaultConfigurationName = Release;
543 | };
544 | /* End XCConfigurationList section */
545 |
546 | /* Begin XCRemoteSwiftPackageReference section */
547 | 4155ECDC254E6F5F00DBDB09 /* XCRemoteSwiftPackageReference "Nimble" */ = {
548 | isa = XCRemoteSwiftPackageReference;
549 | repositoryURL = "https://github.com/Quick/Nimble";
550 | requirement = {
551 | kind = exactVersion;
552 | version = 9.0.0;
553 | };
554 | };
555 | 4155ECDF254E6FFB00DBDB09 /* XCRemoteSwiftPackageReference "Quick" */ = {
556 | isa = XCRemoteSwiftPackageReference;
557 | repositoryURL = "https://github.com/Quick/Quick";
558 | requirement = {
559 | kind = exactVersion;
560 | version = 3.0.0;
561 | };
562 | };
563 | /* End XCRemoteSwiftPackageReference section */
564 |
565 | /* Begin XCSwiftPackageProductDependency section */
566 | 41E8A258255623EC009DF7C9 /* Quick */ = {
567 | isa = XCSwiftPackageProductDependency;
568 | package = 4155ECDF254E6FFB00DBDB09 /* XCRemoteSwiftPackageReference "Quick" */;
569 | productName = Quick;
570 | };
571 | 41E8A25C255623F5009DF7C9 /* Nimble */ = {
572 | isa = XCSwiftPackageProductDependency;
573 | package = 4155ECDC254E6F5F00DBDB09 /* XCRemoteSwiftPackageReference "Nimble" */;
574 | productName = Nimble;
575 | };
576 | /* End XCSwiftPackageProductDependency section */
577 | };
578 | rootObject = 607FACC81AFB9204008FA782 /* Project object */;
579 | }
580 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "CwlCatchException",
6 | "repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "f809deb30dc5c9d9b78c872e553261a61177721a",
10 | "version": "2.0.0"
11 | }
12 | },
13 | {
14 | "package": "CwlPreconditionTesting",
15 | "repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "02b7a39a99c4da27abe03cab2053a9034379639f",
19 | "version": "2.0.0"
20 | }
21 | },
22 | {
23 | "package": "Nimble",
24 | "repositoryURL": "https://github.com/Quick/Nimble",
25 | "state": {
26 | "branch": null,
27 | "revision": "e491a6731307bb23783bf664d003be9b2fa59ab5",
28 | "version": "9.0.0"
29 | }
30 | },
31 | {
32 | "package": "Quick",
33 | "repositoryURL": "https://github.com/Quick/Quick",
34 | "state": {
35 | "branch": null,
36 | "revision": "0038bcbab4292f3b028632556507c124e5ba69f3",
37 | "version": "3.0.0"
38 | }
39 | }
40 | ]
41 | },
42 | "version": 1
43 | }
44 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/xcshareddata/xcschemes/CardStackView_Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
64 |
70 |
71 |
72 |
73 |
79 |
81 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Example/CardStackView.xcodeproj/xcshareddata/xcschemes/CardStackView_Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
14 |
15 |
17 |
23 |
24 |
25 |
26 |
27 |
37 |
38 |
44 |
45 |
47 |
48 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Example/CardStackView/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // CardStackView
4 | //
5 | // Created by gomfucius on 07/23/2017.
6 | // Copyright (c) 2017 gomfucius. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/Example/CardStackView/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/CardStackView/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/CardStackView/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/Example/CardStackView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/CardStackView/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // CardStackView
4 | //
5 | // Created by Genki Mine on 7/9/17.
6 | // Copyright © 2017 Genki. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | self.view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
17 |
18 | var cardViews = [UIView]()
19 |
20 | for index in 0...6 {
21 | let view = UIView()
22 | view.backgroundColor = UIColor.white
23 |
24 | let mainLabel = UILabel(frame: CGRect(x: 40, y: 40, width: 100, height: 100))
25 | mainLabel.text = "#\(index)"
26 | mainLabel.textColor = UIColor.gray
27 | mainLabel.font = UIFont.systemFont(ofSize: 24.0)
28 | view.addSubview(mainLabel)
29 |
30 | view.layer.cornerRadius = 10.0
31 | view.layer.borderColor = UIColor.lightGray.cgColor
32 | view.layer.borderWidth = 0.5
33 | view.layer.shadowColor = UIColor.lightGray.cgColor
34 | view.layer.shadowRadius = 2.0
35 | view.layer.shadowOffset = CGSize(width: 4, height: 4)
36 | view.layer.shadowOpacity = 0.2
37 | view.clipsToBounds = false
38 | view.layer.rasterizationScale = UIScreen.main.scale
39 | view.layer.shouldRasterize = true
40 |
41 | cardViews.append(view)
42 | }
43 |
44 | cardViews.reverse()
45 |
46 | let cardStackView = CardStackView(cards: cardViews, showsPagination: true, maxAngle: 10, randomAngle: true, throwDuration: 0.4)
47 | cardStackView.translatesAutoresizingMaskIntoConstraints = false
48 | cardStackView.delegate = self
49 | self.view.addSubview(cardStackView)
50 | let views = ["cardStackView": cardStackView]
51 |
52 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|-80-[cardStackView]-80-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
53 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-100-[cardStackView]-100-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
54 | }
55 | }
56 |
57 | // MARK: - CardStackViewDelegate
58 |
59 | extension ViewController: CardStackViewDelegate {
60 |
61 | func cardStackViewDidChangePage(_ cardStackView: CardStackView) {
62 | print("Current index: \(cardStackView.currentIndex)")
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/Example/Tests/CardStackViewSpec.swift:
--------------------------------------------------------------------------------
1 | // https://github.com/Quick/Quick
2 |
3 | import UIKit
4 | import Quick
5 | import Nimble
6 |
7 | class CardStackViewSpec: QuickSpec {
8 |
9 | override func spec() {
10 | describe("init") {
11 | context("if array of UIViews are empty") {
12 | let cardStackView = CardStackView(cards: [])
13 | it("should not have pagination view") {
14 | expect(cardStackView.paginationView).to(beNil())
15 | }
16 | }
17 |
18 | context("if array of UIViews have values") {
19 | let cardStackView = CardStackView(cards: [UIView(), UIView()])
20 | it("should have pagination view") {
21 | expect(cardStackView.paginationView).toNot(beNil())
22 | }
23 | }
24 |
25 | context("if array of UIViews have values and pagination is false") {
26 | let cardStackView = CardStackView(cards: [UIView(), UIView()], showsPagination: false)
27 | it("should not have pagination view") {
28 | expect(cardStackView.paginationView).to(beNil())
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/Example/Tests/CardViewSpec.swift:
--------------------------------------------------------------------------------
1 | // https://github.com/Quick/Quick
2 |
3 | import Quick
4 | import Nimble
5 | import UIKit
6 |
7 | class CardViewSpec: QuickSpec {
8 |
9 | override func spec() {
10 | describe("init") {
11 | let cardView = CardView(view: UIView(frame: CGRect(x: 10.0, y: 10.0, width: 10.0, height: 10.0)), angle: 10.0)
12 | it("should not have originalBounds yet") {
13 | expect(cardView.originalBounds).to(beNil())
14 | expect(cardView.originalCenter).to(beNil())
15 | }
16 | }
17 |
18 | describe("layoutSubviews") {
19 | let cardView = CardView(view: UIView(frame: CGRect(x: 10.0, y: 10.0, width: 10.0, height: 10.0)), angle: 10.0)
20 | var stackView: CardStackView!
21 |
22 | beforeEach {
23 | let parentViewController = UIViewController()
24 | parentViewController.view = UIView(frame: CGRect(x: 10.0, y: 10.0, width: 10.0, height: 10.0))
25 | let parentView = parentViewController.view!
26 | stackView = CardStackView(cards: [cardView])
27 | parentView.addSubview(stackView)
28 | stackView.translatesAutoresizingMaskIntoConstraints = false
29 | let views: [String: UIView] = ["stackView": stackView]
30 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[stackView]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
31 | NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stackView]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
32 | parentView.layoutIfNeeded()
33 | }
34 |
35 | context("layoutSubviews") {
36 | it("should have originalBounds") {
37 | expect(cardView.originalBounds) != CGRect.zero
38 | expect(cardView.originalCenter) != CGPoint.zero
39 | }
40 | }
41 |
42 | context("resetPositionAndRotation") {
43 | it("should eventually go back to original point") {
44 | let newCenter = CGPoint(x: 1.0, y: 1.0)
45 | expect(cardView.center).notTo(equal(newCenter))
46 | cardView.center = newCenter
47 | expect(cardView.center).notTo(equal(cardView.originalCenter))
48 | cardView.resetPositionAndRotation(withElasticity: true)
49 | expect(cardView.center).toEventually(equal(cardView.originalCenter))
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/Example/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Tests/PaginationViewSpec.swift:
--------------------------------------------------------------------------------
1 | // https://github.com/Quick/Quick
2 |
3 | import Quick
4 | import Nimble
5 |
6 | class PaginationViewSpec: QuickSpec {
7 |
8 | override func spec() {
9 | describe("init") {
10 | let paginationView = PaginationView(pages: 10)
11 |
12 | context("if pages is 10 and increments numbers") {
13 | it("should have correct indexes") {
14 | expect(paginationView.currentIndex) == 0
15 | expect(paginationView.maxIndex) == 9
16 |
17 | paginationView.incrementPage(by: 1)
18 | expect(paginationView.currentIndex) == 1
19 |
20 | paginationView.incrementPage(by: -1)
21 | expect(paginationView.currentIndex) == 0
22 |
23 | paginationView.incrementPage(by: -1)
24 | expect(paginationView.currentIndex) == paginationView.maxIndex
25 | }
26 | }
27 | }
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/Example/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gomfucius/CardStackView/941769f3435c9adcdca7b3236ca6e5cda7ae8d46/Example/example.gif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Genki Mine
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.0
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "CardStackView",
8 | products: [
9 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
10 | .library(
11 | name: "CardStackView",
12 | targets: ["CardStackView"]),
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
21 | .target(
22 | name: "CardStackView",
23 | dependencies: []),
24 | .testTarget(
25 | name: "CardStackViewTests",
26 | dependencies: ["CardStackView"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # 🎴 CardStackView
3 |
4 | [](https://swift.org)
5 | [](https://github.com/gomfucius/CardStackView/actions)
6 | [](https://github.com/Carthage/Carthage)
7 | [](http://cocoapods.org/pods/CardStackView)
8 | [](http://cocoapods.org/pods/CardStackView)
9 | [](http://cocoapods.org/pods/CardStackView)
10 | [](https://coveralls.io/github/gomfucius/CardStackView?branch=master)
11 |
12 | 
13 |
14 | ## 😃 Example Project
15 |
16 | To run the example project, clone the repo, open Example/CardStackView.xcodeproj, then build and run the CardStackView_Example target.
17 |
18 | ## 🖥 Installation
19 |
20 | CardStackView is available through [Swift Package Manager](https://developer.apple.com/documentation/swift_packages), [Carthage](https://github.com/Carthage/Carthage) and [CocoaPods](https://cocoapods.org).
21 |
22 | ### Carthage
23 |
24 | github "gomfucius/CardStackView" == 0.2.1
25 |
26 | ### Cocoapods
27 |
28 | To install, simply add the following line to your Podfile:
29 |
30 | ```ruby
31 | pod "CardStackView"
32 | ```
33 |
34 | ## 🤔 Implementation
35 |
36 | ```swift
37 | import CardStackView
38 |
39 | class ViewController: UIViewController {
40 |
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 |
44 | var cardViews = [MyCustomView]()
45 |
46 | for index in 0...6 {
47 | var view = MyCustomView()
48 | cardViews.append(view)
49 | }
50 |
51 | let cardStackView = CardStackView(cards: cardViews)
52 | self.view.addSubview(cardStackView)
53 |
54 | // autolayout your cardStackView
55 | }
56 | }
57 | ```
58 |
59 | ## 🤓 Author
60 |
61 | gomfucius, gomfucius@gmail.com
62 |
63 | ## 📄 License
64 |
65 | CardStackView is available under the MIT license. See the LICENSE file for more info.
66 |
--------------------------------------------------------------------------------
/Sources/CardStackView/CardStackView.swift:
--------------------------------------------------------------------------------
1 | struct CardStackView {
2 | var text = "Hello, World!"
3 | }
4 |
--------------------------------------------------------------------------------
/Tests/CardStackViewTests/CardStackViewTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import CardStackView
3 |
4 | final class CardStackViewTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertEqual(CardStackView().text, "Hello, World!")
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/CardStackViewTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(CardStackViewTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import CardStackViewTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += CardStackViewTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------