├── Animate.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ ├── Animate-iOS.xcscheme
│ │ └── Animate-tvOS.xcscheme
└── project.pbxproj
├── README.md
├── Animate.podspec
├── Configs
└── Animate.plist
├── LICENSE
├── .gitignore
└── Sources
└── Animate.swift
/Animate.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Animate
2 |
3 | This repository contains a reference implementation from my two-part blog post *["Building a declarative animation framework in Swift"](https://www.swiftbysundell.com/posts/building-a-declarative-animation-framework-in-swift-part-1)*. Note that it's not intended to be used as-is. Instead, it's an example that you can easily build your own animation frameworks on top of.
4 |
5 | For questions, comments or feedback, feel free to contact me [on Twitter @johnsundell](https://twitter.com/johnsundell).
6 |
7 | Happy animating! 🚀
8 |
--------------------------------------------------------------------------------
/Animate.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "Animate"
3 | s.version = "1.0"
4 | s.summary = "Declarative UIView animations without nested closures"
5 | s.description = <<-DESC
6 | Animate is a small framework that enables you to define UIView animations using a declarative API
7 | DESC
8 | s.homepage = "https://github.com/JohnSundell/Animate"
9 | s.license = { :type => "MIT", :file => "LICENSE" }
10 | s.author = { "John Sundell" => "john@sundell.co" }
11 | s.social_media_url = "https://twitter.com/johnsundell"
12 | s.ios.deployment_target = "8.0"
13 | s.tvos.deployment_target = "9.0"
14 | s.source = { :git => "https://github.com/JohnSundell/Animate.git", :tag => s.version.to_s }
15 | s.source_files = "Sources/**/*"
16 | s.frameworks = "Foundation"
17 | end
18 |
--------------------------------------------------------------------------------
/Configs/Animate.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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSHumanReadableCopyright
24 | Copyright © 2017 John Sundell. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 John Sundell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 | .DS_Store
20 |
21 | ## Other
22 | *.moved-aside
23 | *.xccheckout
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 | *.dSYM.zip
30 | *.dSYM
31 |
32 | ## Playgrounds
33 | timeline.xctimeline
34 | playground.xcworkspace
35 |
36 | # Swift Package Manager
37 | #
38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
39 | # Packages/
40 | # Package.pins
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | # fastlane
59 | #
60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
61 | # screenshots whenever they are needed.
62 | # For more information about the recommended setup visit:
63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
64 |
65 | fastlane/report.xml
66 | fastlane/Preview.html
67 | fastlane/screenshots
68 | fastlane/test_output
69 |
--------------------------------------------------------------------------------
/Animate.xcodeproj/xcshareddata/xcschemes/Animate-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Animate.xcodeproj/xcshareddata/xcschemes/Animate-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Sources/Animate.swift:
--------------------------------------------------------------------------------
1 | /**
2 | * Animate
3 | * Copyright (c) John Sundell 2017
4 | * Licensed under the MIT license. See LICENSE file.
5 | */
6 |
7 | import UIKit
8 |
9 | // MARK: - Public
10 |
11 | public struct Animation {
12 | public let duration: TimeInterval
13 | public let closure: (UIView) -> Void
14 |
15 | public init(duration: TimeInterval, closure: @escaping (UIView) -> Void) {
16 | self.duration = duration
17 | self.closure = closure
18 | }
19 | }
20 |
21 | public extension Animation {
22 | static func fadeIn(duration: TimeInterval = 0.3) -> Animation {
23 | return Animation(duration: duration) { $0.alpha = 1 }
24 | }
25 |
26 | static func fadeOut(duration: TimeInterval = 0.3) -> Animation {
27 | return Animation(duration: duration) { $0.alpha = 0 }
28 | }
29 |
30 | static func resize(to size: CGSize, duration: TimeInterval = 0.3) -> Animation {
31 | return Animation(duration: duration) { $0.bounds.size = size }
32 | }
33 |
34 | static func move(byX x: CGFloat, y: CGFloat, duration: TimeInterval = 0.3) -> Animation {
35 | return Animation(duration: duration) {
36 | $0.center.x += x
37 | $0.center.y += y
38 | }
39 | }
40 | }
41 |
42 | public final class AnimationToken {
43 | private let view: UIView
44 | private let animations: [Animation]
45 | private let mode: AnimationMode
46 | private var isValid = true
47 |
48 | internal init(view: UIView, animations: [Animation], mode: AnimationMode) {
49 | self.view = view
50 | self.animations = animations
51 | self.mode = mode
52 | }
53 |
54 | deinit {
55 | perform {}
56 | }
57 |
58 | internal func perform(completionHandler: @escaping () -> Void) {
59 | guard isValid else {
60 | return
61 | }
62 |
63 | isValid = false
64 |
65 | switch mode {
66 | case .inSequence:
67 | view.performAnimations(animations, completionHandler: completionHandler)
68 | case .inParallel:
69 | view.performAnimationsInParallel(animations, completionHandler: completionHandler)
70 | }
71 | }
72 | }
73 |
74 | public func animate(_ tokens: [AnimationToken]) {
75 | guard !tokens.isEmpty else {
76 | return
77 | }
78 |
79 | var tokens = tokens
80 | let token = tokens.removeFirst()
81 |
82 | token.perform {
83 | animate(tokens)
84 | }
85 | }
86 |
87 | public func animate(_ tokens: AnimationToken...) {
88 | animate(tokens)
89 | }
90 |
91 | public extension UIView {
92 | @discardableResult func animate(_ animations: [Animation]) -> AnimationToken {
93 | return AnimationToken(
94 | view: self,
95 | animations: animations,
96 | mode: .inSequence
97 | )
98 | }
99 |
100 | @discardableResult func animate(_ animations: Animation...) -> AnimationToken {
101 | return animate(animations)
102 | }
103 |
104 | @discardableResult func animate(inParallel animations: [Animation]) -> AnimationToken {
105 | return AnimationToken(
106 | view: self,
107 | animations: animations,
108 | mode: .inParallel
109 | )
110 | }
111 |
112 | @discardableResult func animate(inParallel animations: Animation...) -> AnimationToken {
113 | return animate(inParallel: animations)
114 | }
115 | }
116 |
117 | // MARK: - Internal
118 |
119 | internal enum AnimationMode {
120 | case inSequence
121 | case inParallel
122 | }
123 |
124 | internal extension UIView {
125 | func performAnimations(_ animations: [Animation], completionHandler: @escaping () -> Void) {
126 | guard !animations.isEmpty else {
127 | return completionHandler()
128 | }
129 |
130 | var animations = animations
131 | let animation = animations.removeFirst()
132 |
133 | UIView.animate(withDuration: animation.duration, animations: {
134 | animation.closure(self)
135 | }, completion: { _ in
136 | self.performAnimations(animations, completionHandler: completionHandler)
137 | })
138 | }
139 |
140 | func performAnimationsInParallel(_ animations: [Animation], completionHandler: @escaping () -> Void) {
141 | guard !animations.isEmpty else {
142 | return completionHandler()
143 | }
144 |
145 | let animationCount = animations.count
146 | var completionCount = 0
147 |
148 | let animationCompletionHandler = {
149 | completionCount += 1
150 |
151 | if completionCount == animationCount {
152 | completionHandler()
153 | }
154 | }
155 |
156 | for animation in animations {
157 | UIView.animate(withDuration: animation.duration, animations: {
158 | animation.closure(self)
159 | }, completion: { _ in
160 | animationCompletionHandler()
161 | })
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/Animate.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 47;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8933C7851EB5B820000D00A4 /* Animate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* Animate.swift */; };
11 | 8933C7881EB5B820000D00A4 /* Animate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* Animate.swift */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXFileReference section */
15 | 52D6D97C1BEFF229002C0205 /* Animate.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Animate.framework; sourceTree = BUILT_PRODUCTS_DIR; };
16 | 52D6D9F01BEFFFBE002C0205 /* Animate.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Animate.framework; sourceTree = BUILT_PRODUCTS_DIR; };
17 | 8933C7841EB5B820000D00A4 /* Animate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animate.swift; sourceTree = ""; };
18 | 8933C7891EB5B82A000D00A4 /* AnimateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimateTests.swift; sourceTree = ""; };
19 | AD2FAA261CD0B6D800659CF4 /* Animate.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Animate.plist; sourceTree = ""; };
20 | AD2FAA281CD0B6E100659CF4 /* AnimateTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AnimateTests.plist; sourceTree = ""; };
21 | /* End PBXFileReference section */
22 |
23 | /* Begin PBXFrameworksBuildPhase section */
24 | 52D6D9781BEFF229002C0205 /* Frameworks */ = {
25 | isa = PBXFrameworksBuildPhase;
26 | buildActionMask = 2147483647;
27 | files = (
28 | );
29 | runOnlyForDeploymentPostprocessing = 0;
30 | };
31 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */ = {
32 | isa = PBXFrameworksBuildPhase;
33 | buildActionMask = 2147483647;
34 | files = (
35 | );
36 | runOnlyForDeploymentPostprocessing = 0;
37 | };
38 | /* End PBXFrameworksBuildPhase section */
39 |
40 | /* Begin PBXGroup section */
41 | 52D6D9721BEFF229002C0205 = {
42 | isa = PBXGroup;
43 | children = (
44 | 8933C7811EB5B7E0000D00A4 /* Sources */,
45 | 8933C7831EB5B7EB000D00A4 /* Tests */,
46 | 52D6D99C1BEFF38C002C0205 /* Configs */,
47 | 52D6D97D1BEFF229002C0205 /* Products */,
48 | );
49 | sourceTree = "";
50 | };
51 | 52D6D97D1BEFF229002C0205 /* Products */ = {
52 | isa = PBXGroup;
53 | children = (
54 | 52D6D97C1BEFF229002C0205 /* Animate.framework */,
55 | 52D6D9F01BEFFFBE002C0205 /* Animate.framework */,
56 | );
57 | name = Products;
58 | sourceTree = "";
59 | };
60 | 52D6D99C1BEFF38C002C0205 /* Configs */ = {
61 | isa = PBXGroup;
62 | children = (
63 | DD7502721C68FC1B006590AF /* Frameworks */,
64 | DD7502731C68FC20006590AF /* Tests */,
65 | );
66 | path = Configs;
67 | sourceTree = "";
68 | };
69 | 8933C7811EB5B7E0000D00A4 /* Sources */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 8933C7841EB5B820000D00A4 /* Animate.swift */,
73 | );
74 | path = Sources;
75 | sourceTree = "";
76 | };
77 | 8933C7831EB5B7EB000D00A4 /* Tests */ = {
78 | isa = PBXGroup;
79 | children = (
80 | 8933C7891EB5B82A000D00A4 /* AnimateTests.swift */,
81 | );
82 | name = Tests;
83 | path = Tests/AnimateTests;
84 | sourceTree = "";
85 | };
86 | DD7502721C68FC1B006590AF /* Frameworks */ = {
87 | isa = PBXGroup;
88 | children = (
89 | AD2FAA261CD0B6D800659CF4 /* Animate.plist */,
90 | );
91 | name = Frameworks;
92 | sourceTree = "";
93 | };
94 | DD7502731C68FC20006590AF /* Tests */ = {
95 | isa = PBXGroup;
96 | children = (
97 | AD2FAA281CD0B6E100659CF4 /* AnimateTests.plist */,
98 | );
99 | name = Tests;
100 | sourceTree = "";
101 | };
102 | /* End PBXGroup section */
103 |
104 | /* Begin PBXHeadersBuildPhase section */
105 | 52D6D9791BEFF229002C0205 /* Headers */ = {
106 | isa = PBXHeadersBuildPhase;
107 | buildActionMask = 2147483647;
108 | files = (
109 | );
110 | runOnlyForDeploymentPostprocessing = 0;
111 | };
112 | 52D6D9ED1BEFFFBE002C0205 /* Headers */ = {
113 | isa = PBXHeadersBuildPhase;
114 | buildActionMask = 2147483647;
115 | files = (
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXHeadersBuildPhase section */
120 |
121 | /* Begin PBXNativeTarget section */
122 | 52D6D97B1BEFF229002C0205 /* Animate-iOS */ = {
123 | isa = PBXNativeTarget;
124 | buildConfigurationList = 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Animate-iOS" */;
125 | buildPhases = (
126 | 52D6D9771BEFF229002C0205 /* Sources */,
127 | 52D6D9781BEFF229002C0205 /* Frameworks */,
128 | 52D6D9791BEFF229002C0205 /* Headers */,
129 | 52D6D97A1BEFF229002C0205 /* Resources */,
130 | );
131 | buildRules = (
132 | );
133 | dependencies = (
134 | );
135 | name = "Animate-iOS";
136 | productName = Animate;
137 | productReference = 52D6D97C1BEFF229002C0205 /* Animate.framework */;
138 | productType = "com.apple.product-type.framework";
139 | };
140 | 52D6D9EF1BEFFFBE002C0205 /* Animate-tvOS */ = {
141 | isa = PBXNativeTarget;
142 | buildConfigurationList = 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "Animate-tvOS" */;
143 | buildPhases = (
144 | 52D6D9EB1BEFFFBE002C0205 /* Sources */,
145 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */,
146 | 52D6D9ED1BEFFFBE002C0205 /* Headers */,
147 | 52D6D9EE1BEFFFBE002C0205 /* Resources */,
148 | );
149 | buildRules = (
150 | );
151 | dependencies = (
152 | );
153 | name = "Animate-tvOS";
154 | productName = "Animate-tvOS";
155 | productReference = 52D6D9F01BEFFFBE002C0205 /* Animate.framework */;
156 | productType = "com.apple.product-type.framework";
157 | };
158 | /* End PBXNativeTarget section */
159 |
160 | /* Begin PBXProject section */
161 | 52D6D9731BEFF229002C0205 /* Project object */ = {
162 | isa = PBXProject;
163 | attributes = {
164 | LastSwiftUpdateCheck = 0720;
165 | LastUpgradeCheck = 0810;
166 | ORGANIZATIONNAME = Animate;
167 | TargetAttributes = {
168 | 52D6D97B1BEFF229002C0205 = {
169 | CreatedOnToolsVersion = 7.1;
170 | LastSwiftMigration = 0800;
171 | };
172 | 52D6D9EF1BEFFFBE002C0205 = {
173 | CreatedOnToolsVersion = 7.1;
174 | LastSwiftMigration = 0800;
175 | };
176 | };
177 | };
178 | buildConfigurationList = 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "Animate" */;
179 | compatibilityVersion = "Xcode 6.3";
180 | developmentRegion = English;
181 | hasScannedForEncodings = 0;
182 | knownRegions = (
183 | en,
184 | );
185 | mainGroup = 52D6D9721BEFF229002C0205;
186 | productRefGroup = 52D6D97D1BEFF229002C0205 /* Products */;
187 | projectDirPath = "";
188 | projectRoot = "";
189 | targets = (
190 | 52D6D97B1BEFF229002C0205 /* Animate-iOS */,
191 | 52D6D9EF1BEFFFBE002C0205 /* Animate-tvOS */,
192 | );
193 | };
194 | /* End PBXProject section */
195 |
196 | /* Begin PBXResourcesBuildPhase section */
197 | 52D6D97A1BEFF229002C0205 /* Resources */ = {
198 | isa = PBXResourcesBuildPhase;
199 | buildActionMask = 2147483647;
200 | files = (
201 | );
202 | runOnlyForDeploymentPostprocessing = 0;
203 | };
204 | 52D6D9EE1BEFFFBE002C0205 /* Resources */ = {
205 | isa = PBXResourcesBuildPhase;
206 | buildActionMask = 2147483647;
207 | files = (
208 | );
209 | runOnlyForDeploymentPostprocessing = 0;
210 | };
211 | /* End PBXResourcesBuildPhase section */
212 |
213 | /* Begin PBXSourcesBuildPhase section */
214 | 52D6D9771BEFF229002C0205 /* Sources */ = {
215 | isa = PBXSourcesBuildPhase;
216 | buildActionMask = 2147483647;
217 | files = (
218 | 8933C7851EB5B820000D00A4 /* Animate.swift in Sources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | 52D6D9EB1BEFFFBE002C0205 /* Sources */ = {
223 | isa = PBXSourcesBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | 8933C7881EB5B820000D00A4 /* Animate.swift in Sources */,
227 | );
228 | runOnlyForDeploymentPostprocessing = 0;
229 | };
230 | /* End PBXSourcesBuildPhase section */
231 |
232 | /* Begin XCBuildConfiguration section */
233 | 52D6D98E1BEFF229002C0205 /* Debug */ = {
234 | isa = XCBuildConfiguration;
235 | buildSettings = {
236 | ALWAYS_SEARCH_USER_PATHS = NO;
237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
238 | CLANG_CXX_LIBRARY = "libc++";
239 | CLANG_ENABLE_MODULES = YES;
240 | CLANG_ENABLE_OBJC_ARC = YES;
241 | CLANG_WARN_BOOL_CONVERSION = YES;
242 | CLANG_WARN_CONSTANT_CONVERSION = YES;
243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
244 | CLANG_WARN_EMPTY_BODY = YES;
245 | CLANG_WARN_ENUM_CONVERSION = YES;
246 | CLANG_WARN_INFINITE_RECURSION = YES;
247 | CLANG_WARN_INT_CONVERSION = YES;
248 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
249 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
250 | CLANG_WARN_UNREACHABLE_CODE = YES;
251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
252 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
253 | COPY_PHASE_STRIP = NO;
254 | CURRENT_PROJECT_VERSION = 1;
255 | DEBUG_INFORMATION_FORMAT = dwarf;
256 | ENABLE_STRICT_OBJC_MSGSEND = YES;
257 | ENABLE_TESTABILITY = YES;
258 | GCC_C_LANGUAGE_STANDARD = gnu99;
259 | GCC_DYNAMIC_NO_PIC = NO;
260 | GCC_NO_COMMON_BLOCKS = YES;
261 | GCC_OPTIMIZATION_LEVEL = 0;
262 | GCC_PREPROCESSOR_DEFINITIONS = (
263 | "DEBUG=1",
264 | "$(inherited)",
265 | );
266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
268 | GCC_WARN_UNDECLARED_SELECTOR = YES;
269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
270 | GCC_WARN_UNUSED_FUNCTION = YES;
271 | GCC_WARN_UNUSED_VARIABLE = YES;
272 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
273 | MTL_ENABLE_DEBUG_INFO = YES;
274 | ONLY_ACTIVE_ARCH = YES;
275 | SDKROOT = iphoneos;
276 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
277 | SWIFT_VERSION = 3.0;
278 | TARGETED_DEVICE_FAMILY = "1,2";
279 | VERSIONING_SYSTEM = "apple-generic";
280 | VERSION_INFO_PREFIX = "";
281 | };
282 | name = Debug;
283 | };
284 | 52D6D98F1BEFF229002C0205 /* Release */ = {
285 | isa = XCBuildConfiguration;
286 | buildSettings = {
287 | ALWAYS_SEARCH_USER_PATHS = NO;
288 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
289 | CLANG_CXX_LIBRARY = "libc++";
290 | CLANG_ENABLE_MODULES = YES;
291 | CLANG_ENABLE_OBJC_ARC = YES;
292 | CLANG_WARN_BOOL_CONVERSION = YES;
293 | CLANG_WARN_CONSTANT_CONVERSION = YES;
294 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
295 | CLANG_WARN_EMPTY_BODY = YES;
296 | CLANG_WARN_ENUM_CONVERSION = YES;
297 | CLANG_WARN_INFINITE_RECURSION = YES;
298 | CLANG_WARN_INT_CONVERSION = YES;
299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
300 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
301 | CLANG_WARN_UNREACHABLE_CODE = YES;
302 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
303 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
304 | COPY_PHASE_STRIP = NO;
305 | CURRENT_PROJECT_VERSION = 1;
306 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
307 | ENABLE_NS_ASSERTIONS = NO;
308 | ENABLE_STRICT_OBJC_MSGSEND = YES;
309 | GCC_C_LANGUAGE_STANDARD = gnu99;
310 | GCC_NO_COMMON_BLOCKS = YES;
311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
313 | GCC_WARN_UNDECLARED_SELECTOR = YES;
314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
315 | GCC_WARN_UNUSED_FUNCTION = YES;
316 | GCC_WARN_UNUSED_VARIABLE = YES;
317 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
318 | MTL_ENABLE_DEBUG_INFO = NO;
319 | SDKROOT = iphoneos;
320 | SWIFT_VERSION = 3.0;
321 | TARGETED_DEVICE_FAMILY = "1,2";
322 | VALIDATE_PRODUCT = YES;
323 | VERSIONING_SYSTEM = "apple-generic";
324 | VERSION_INFO_PREFIX = "";
325 | };
326 | name = Release;
327 | };
328 | 52D6D9911BEFF229002C0205 /* Debug */ = {
329 | isa = XCBuildConfiguration;
330 | buildSettings = {
331 | APPLICATION_EXTENSION_API_ONLY = YES;
332 | CLANG_ENABLE_MODULES = YES;
333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
334 | DEFINES_MODULE = YES;
335 | DYLIB_COMPATIBILITY_VERSION = 1;
336 | DYLIB_CURRENT_VERSION = 1;
337 | DYLIB_INSTALL_NAME_BASE = "@rpath";
338 | INFOPLIST_FILE = Configs/Animate.plist;
339 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
340 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
341 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
342 | ONLY_ACTIVE_ARCH = NO;
343 | PRODUCT_BUNDLE_IDENTIFIER = "com.Animate.Animate-iOS";
344 | PRODUCT_NAME = Animate;
345 | SKIP_INSTALL = YES;
346 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
347 | SWIFT_VERSION = 3.0;
348 | };
349 | name = Debug;
350 | };
351 | 52D6D9921BEFF229002C0205 /* Release */ = {
352 | isa = XCBuildConfiguration;
353 | buildSettings = {
354 | APPLICATION_EXTENSION_API_ONLY = YES;
355 | CLANG_ENABLE_MODULES = YES;
356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
357 | DEFINES_MODULE = YES;
358 | DYLIB_COMPATIBILITY_VERSION = 1;
359 | DYLIB_CURRENT_VERSION = 1;
360 | DYLIB_INSTALL_NAME_BASE = "@rpath";
361 | INFOPLIST_FILE = Configs/Animate.plist;
362 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
363 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
364 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
365 | PRODUCT_BUNDLE_IDENTIFIER = "com.Animate.Animate-iOS";
366 | PRODUCT_NAME = Animate;
367 | SKIP_INSTALL = YES;
368 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
369 | SWIFT_VERSION = 3.0;
370 | };
371 | name = Release;
372 | };
373 | 52D6DA021BEFFFBE002C0205 /* Debug */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | APPLICATION_EXTENSION_API_ONLY = YES;
377 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
378 | DEFINES_MODULE = YES;
379 | DYLIB_COMPATIBILITY_VERSION = 1;
380 | DYLIB_CURRENT_VERSION = 1;
381 | DYLIB_INSTALL_NAME_BASE = "@rpath";
382 | INFOPLIST_FILE = Configs/Animate.plist;
383 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
385 | PRODUCT_BUNDLE_IDENTIFIER = "com.Animate.Animate-tvOS";
386 | PRODUCT_NAME = Animate;
387 | SDKROOT = appletvos;
388 | SKIP_INSTALL = YES;
389 | SWIFT_VERSION = 3.0;
390 | TARGETED_DEVICE_FAMILY = 3;
391 | TVOS_DEPLOYMENT_TARGET = 9.0;
392 | };
393 | name = Debug;
394 | };
395 | 52D6DA031BEFFFBE002C0205 /* Release */ = {
396 | isa = XCBuildConfiguration;
397 | buildSettings = {
398 | APPLICATION_EXTENSION_API_ONLY = YES;
399 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
400 | DEFINES_MODULE = YES;
401 | DYLIB_COMPATIBILITY_VERSION = 1;
402 | DYLIB_CURRENT_VERSION = 1;
403 | DYLIB_INSTALL_NAME_BASE = "@rpath";
404 | INFOPLIST_FILE = Configs/Animate.plist;
405 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
406 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
407 | PRODUCT_BUNDLE_IDENTIFIER = "com.Animate.Animate-tvOS";
408 | PRODUCT_NAME = Animate;
409 | SDKROOT = appletvos;
410 | SKIP_INSTALL = YES;
411 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
412 | SWIFT_VERSION = 3.0;
413 | TARGETED_DEVICE_FAMILY = 3;
414 | TVOS_DEPLOYMENT_TARGET = 9.0;
415 | };
416 | name = Release;
417 | };
418 | /* End XCBuildConfiguration section */
419 |
420 | /* Begin XCConfigurationList section */
421 | 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "Animate" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | 52D6D98E1BEFF229002C0205 /* Debug */,
425 | 52D6D98F1BEFF229002C0205 /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Animate-iOS" */ = {
431 | isa = XCConfigurationList;
432 | buildConfigurations = (
433 | 52D6D9911BEFF229002C0205 /* Debug */,
434 | 52D6D9921BEFF229002C0205 /* Release */,
435 | );
436 | defaultConfigurationIsVisible = 0;
437 | defaultConfigurationName = Release;
438 | };
439 | 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "Animate-tvOS" */ = {
440 | isa = XCConfigurationList;
441 | buildConfigurations = (
442 | 52D6DA021BEFFFBE002C0205 /* Debug */,
443 | 52D6DA031BEFFFBE002C0205 /* Release */,
444 | );
445 | defaultConfigurationIsVisible = 0;
446 | defaultConfigurationName = Release;
447 | };
448 | /* End XCConfigurationList section */
449 | };
450 | rootObject = 52D6D9731BEFF229002C0205 /* Project object */;
451 | }
452 |
--------------------------------------------------------------------------------