├── gemfile
├── Resources
└── boardingPass.gif
├── .swiftlint.yml
├── BoardingPass.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── mskiba.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── BoardingPass.xcscheme
└── project.pbxproj
├── BoardingPass
├── Assets
│ ├── BoardingPass.h
│ └── Info.plist
├── HorizontalSlideAnimatedTransition.swift
├── BoardingInformation.swift
├── BoardingPassCompatibility.swift
└── BoardingNavigationController.swift
├── BoardingPassTests
├── Assets
│ └── Info.plist
└── BoardingPassTests.swift
├── BoardingPassExample
├── App Delegate
│ └── AppDelegate.swift
├── Onboarding Demo
│ ├── Process View Controllers
│ │ ├── SecondViewController.swift
│ │ ├── ThirdViewController.swift
│ │ ├── FirstViewController.swift
│ │ └── ActionableViewController.swift
│ ├── Completed View Controller
│ │ └── CompletedViewController.swift
│ └── OnboardingWrapperViewController.swift
└── Assets
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Info.plist
│ └── Base.lproj
│ └── LaunchScreen.storyboard
├── BoardingPass.podspec
├── LICENSE
├── .travis.yml
├── .gitignore
├── Gemfile.lock
├── CONTRIBUTING.md
└── README.md
/gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem 'cocoapods', '~> 1.1'
4 |
--------------------------------------------------------------------------------
/Resources/boardingPass.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rightpoint/BoardingPass/HEAD/Resources/boardingPass.gif
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | statement_position:
2 | statement_mode: uncuddled_else
3 |
4 | trailing_comma:
5 | mandatory_comma: true
6 |
7 | disabled_rules:
8 | - line_length
9 |
--------------------------------------------------------------------------------
/BoardingPass.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/BoardingPass/Assets/BoardingPass.h:
--------------------------------------------------------------------------------
1 | //
2 | // BoardingPass.h
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/19/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for BoardingPass.
12 | FOUNDATION_EXPORT double BoardingPassVersionNumber;
13 |
14 | //! Project version string for BoardingPass.
15 | FOUNDATION_EXPORT const unsigned char BoardingPassVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/BoardingPassTests/Assets/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 |
--------------------------------------------------------------------------------
/BoardingPassExample/App Delegate/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // BoardingPassExample
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | window = UIWindow(frame: UIScreen.main.bounds)
19 |
20 | window?.rootViewController = OnboardingNavigationViewController.sampleOnboarding()
21 | window?.makeKeyAndVisible()
22 | window?.tintColor = UIColor.red
23 | return true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/Process View Controllers/SecondViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SecondViewController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BoardingPass
11 |
12 | class SecondViewController: ActionableViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | navigationItem.title = NSLocalizedString("Second", comment: "Second View controller title")
17 | }
18 |
19 | }
20 |
21 | extension SecondViewController: BackgroundColorProvider {
22 |
23 | var backgroundColor: UIColor {
24 | return UIColor(white: 0.5, alpha: 1)
25 | }
26 |
27 | var currentProgress: Progress {
28 | return Progress(completedUnitCount: 2, totalUnitCount: 4)
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/BoardingPassTests/BoardingPassTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BoardingPassTests.swift
3 | // BoardingPassTests
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class BoardingPassTests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 | func testExample() {
24 | // This is an example of a functional test case.
25 | // Use XCTAssert and related functions to verify your tests produce the correct results.
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/BoardingPass/Assets/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 | FMWK
17 | CFBundleShortVersionString
18 | 0.2.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/Process View Controllers/ThirdViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ThirdViewController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BoardingPass
11 |
12 | class ThirdViewController: ActionableViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | navigationItem.title = NSLocalizedString("Third", comment: "Third View controller title")
17 | }
18 |
19 | }
20 |
21 | extension ThirdViewController: BackgroundColorProvider {
22 |
23 | var backgroundColor: UIColor {
24 | return .lightGray
25 | }
26 |
27 | var currentProgress: Progress {
28 | return Progress(completedUnitCount: 3, totalUnitCount: 4)
29 | }
30 |
31 | }
32 |
33 | extension ThirdViewController: BoardingInformation {
34 |
35 | var nextViewController: UIViewController? {
36 | return CompletedViewController()
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/BoardingPass.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'BoardingPass'
3 | s.version = '0.2.1'
4 | s.summary = 'A navigation controller interactive pan to push and pop.'
5 |
6 | s.description = <<-DESC
7 | BoardingPass is a subclass of `UINavigationController` with interactive push
8 | and pop gestures. It offers behaviors similar to `UIPageViewController`,
9 | but with all of the familiar behaviors of navigation controller, and the
10 | ability to add fancy effects by animating alongside transitions.
11 | DESC
12 |
13 | s.homepage = 'https://github.com/Raizlabs/BoardingPass'
14 | s.license = { :type => 'MIT', :file => 'LICENSE' }
15 | s.author = { 'Michael Skiba' => 'mike.skiba@raizlabs.com' }
16 | s.source = { :git => 'https://github.com/Raizlabs/BoardingPass.git', :tag => s.version.to_s }
17 | s.social_media_url = 'https://twitter.com/atelierclkwrk'
18 |
19 | s.ios.deployment_target = '9.0'
20 |
21 | s.source_files = 'BoardingPass/**/*'
22 |
23 | s.frameworks = 'Foundation', 'UIKit'
24 |
25 | end
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Raizlabs
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 |
--------------------------------------------------------------------------------
/BoardingPass.xcodeproj/xcuserdata/mskiba.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | BoardingPass.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 | BoardingPassExample.xcscheme
13 |
14 | orderHint
15 | 2
16 |
17 | BoardingPassTests.xcscheme
18 |
19 | isShown
20 |
21 | orderHint
22 | 1
23 |
24 |
25 | SuppressBuildableAutocreation
26 |
27 | 72BE8D651D3EC55E005720FB
28 |
29 | primary
30 |
31 |
32 | 72BE8D741D3FBC05005720FB
33 |
34 | primary
35 |
36 |
37 | 72BE8D831D3FBCDE005720FB
38 |
39 | primary
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | env:
2 | global:
3 | - LC_CTYPE=en_US.UTF-8
4 |
5 | branches:
6 | only:
7 | - develop
8 | - master
9 |
10 | os: osx
11 | language: objective-c
12 | matrix:
13 | exclude:
14 | - os: osx
15 | include:
16 | - osx_image: xcode8
17 | env:
18 | - XCODE_ACTION="clean test"
19 | XCODE_TOOLCHAIN="swift"
20 | XCODE_DESTINATION="platform=iOS Simulator,id=237D7619-4A4E-4624-8925-67A42A8A690A"
21 | - osx_image: xcode8
22 | env:
23 | - JOB=CARTHAGE
24 | script:
25 | - brew update 1> /dev/null 2> /dev/null
26 | - brew outdated carthage || brew upgrade carthage
27 | - carthage build --no-skip-current
28 | - test -d Carthage/Build/iOS/BoardingPass.framework || exit 1
29 | - osx_image: xcode8
30 | env:
31 | - JOB=COCOAPODS
32 | script:
33 | - bundle exec pod lib lint --sources="https://github.com/Raizlabs/BoardingPass"
34 |
35 | before_script:
36 | - killall "Simulator" || echo "No matching processes belonging to you were found"
37 |
38 | script:
39 | - travis_retry xcodebuild ${XCODE_ACTION}
40 | -toolchain ${XCODE_TOOLCHAIN}
41 | -project BoardingPass.xcodeproj
42 | -scheme BoardingPass
43 | -destination "${XCODE_DESTINATION}"
44 |
--------------------------------------------------------------------------------
/BoardingPassExample/Assets/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/BoardingPassExample/Assets/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 | 0.2.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.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 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/Process View Controllers/FirstViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FirstViewController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BoardingPass
11 |
12 | class FirstViewController: ActionableViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | navigationItem.title = NSLocalizedString("First", comment: "First View controller title")
17 | }
18 |
19 | }
20 |
21 | extension FirstViewController: BackgroundColorProvider {
22 |
23 | var backgroundColor: UIColor {
24 | return .darkGray
25 | }
26 |
27 | var currentProgress: Progress {
28 | return Progress(completedUnitCount: 1, totalUnitCount: 4)
29 | }
30 |
31 | }
32 |
33 | extension Progress {
34 | convenience init(completedUnitCount: Int64, totalUnitCount: Int64) {
35 | self.init(totalUnitCount: totalUnitCount)
36 | self.completedUnitCount = completedUnitCount
37 | }
38 | }
39 |
40 | extension UIButton {
41 |
42 | convenience init(title: String, font: UIFont) {
43 | self.init(type:.system)
44 | setTitle(title, for: UIControlState())
45 | titleLabel?.font = font
46 | }
47 |
48 | }
49 |
50 | extension UIBarButtonItem {
51 | static var backButton: UIBarButtonItem {
52 | return UIBarButtonItem(title: NSLocalizedString("Back", comment: "generic back button title"), style: .plain, target: nil, action: nil)
53 | }
54 |
55 | static var skipButton: UIBarButtonItem {
56 | return UIBarButtonItem(title: NSLocalizedString("Skip", comment: "generic skip button title"), style: .plain, target: nil, action: nil)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/BoardingPassExample/Assets/Base.lproj/LaunchScreen.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 |
27 |
28 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (2.3.5)
5 | activesupport (4.2.8)
6 | i18n (~> 0.7)
7 | minitest (~> 5.1)
8 | thread_safe (~> 0.3, >= 0.3.4)
9 | tzinfo (~> 1.1)
10 | claide (1.0.1)
11 | cocoapods (1.2.0)
12 | activesupport (>= 4.0.2, < 5)
13 | claide (>= 1.0.1, < 2.0)
14 | cocoapods-core (= 1.2.0)
15 | cocoapods-deintegrate (>= 1.0.1, < 2.0)
16 | cocoapods-downloader (>= 1.1.3, < 2.0)
17 | cocoapods-plugins (>= 1.0.0, < 2.0)
18 | cocoapods-search (>= 1.0.0, < 2.0)
19 | cocoapods-stats (>= 1.0.0, < 2.0)
20 | cocoapods-trunk (>= 1.1.2, < 2.0)
21 | cocoapods-try (>= 1.1.0, < 2.0)
22 | colored (~> 1.2)
23 | escape (~> 0.0.4)
24 | fourflusher (~> 2.0.1)
25 | gh_inspector (~> 1.0)
26 | molinillo (~> 0.5.5)
27 | nap (~> 1.0)
28 | ruby-macho (~> 0.2.5)
29 | xcodeproj (>= 1.4.1, < 2.0)
30 | cocoapods-core (1.2.0)
31 | activesupport (>= 4.0.2, < 5)
32 | fuzzy_match (~> 2.0.4)
33 | nap (~> 1.0)
34 | cocoapods-deintegrate (1.0.1)
35 | cocoapods-downloader (1.1.3)
36 | cocoapods-plugins (1.0.0)
37 | nap
38 | cocoapods-search (1.0.0)
39 | cocoapods-stats (1.0.0)
40 | cocoapods-trunk (1.1.2)
41 | nap (>= 0.8, < 2.0)
42 | netrc (= 0.7.8)
43 | cocoapods-try (1.1.0)
44 | colored (1.2)
45 | escape (0.0.4)
46 | fourflusher (2.0.1)
47 | fuzzy_match (2.0.4)
48 | gh_inspector (1.0.3)
49 | i18n (0.8.1)
50 | minitest (5.10.1)
51 | molinillo (0.5.6)
52 | nanaimo (0.2.3)
53 | nap (1.1.0)
54 | netrc (0.7.8)
55 | ruby-macho (0.2.6)
56 | thread_safe (0.3.6)
57 | tzinfo (1.2.2)
58 | thread_safe (~> 0.1)
59 | xcodeproj (1.4.2)
60 | CFPropertyList (~> 2.3.3)
61 | activesupport (>= 3)
62 | claide (>= 1.0.1, < 2.0)
63 | colored (~> 1.2)
64 | nanaimo (~> 0.2.3)
65 |
66 | PLATFORMS
67 | ruby
68 |
69 | DEPENDENCIES
70 | cocoapods (~> 1.1)
71 |
72 | BUNDLED WITH
73 | 1.14.5
74 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/Completed View Controller/CompletedViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CompletedViewController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BoardingPass
11 |
12 | class CompletedViewController: UIViewController {
13 |
14 | weak var onboardingDelegate: OnboardingViewControllerDelegate?
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 | navigationItem.hidesBackButton = true
19 | navigationItem.title = NSLocalizedString("Completed", comment: "completed onboarding title")
20 | let resetButton = UIButton(title: NSLocalizedString("Reset", comment: "Reset button title"), font: .onboardingFont)
21 | resetButton.addTarget(self, action: #selector(handleResetTapped), for: .touchUpInside)
22 | view.addSubview(resetButton)
23 | let constraints: [NSLayoutConstraint] = [
24 | resetButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
25 | bottomLayoutGuide.topAnchor.constraint(equalTo: resetButton.bottomAnchor, constant: 10),
26 | ]
27 | resetButton.translatesAutoresizingMaskIntoConstraints = false
28 | NSLayoutConstraint.activate(constraints)
29 | }
30 |
31 | override func viewWillAppear(_ animated: Bool) {
32 | super.viewWillAppear(animated)
33 | let factory: AnimationFactory = { [unowned self] (_, _) in
34 | return self.animation
35 | }
36 | perform(coordinatedAnimations: factory)
37 | }
38 | }
39 |
40 | extension CompletedViewController: BackgroundColorProvider {
41 |
42 | var backgroundColor: UIColor {
43 | return .white
44 | }
45 |
46 | var currentProgress: Progress {
47 | return Progress(completedUnitCount: 4, totalUnitCount: 4)
48 | }
49 |
50 | }
51 |
52 | private extension CompletedViewController {
53 | @objc func handleResetTapped(_ sender: UIButton) {
54 | guard let origin = navigationController?.viewControllers.first else {
55 | return
56 | }
57 | _ = navigationController?.popToViewController(origin, animated: true)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/Process View Controllers/ActionableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActionableViewController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/27/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BoardingPass
11 |
12 | class ActionableViewController: UIViewController {
13 |
14 | weak var onboardingDelegate: OnboardingViewControllerDelegate?
15 |
16 | override func viewDidLoad() {
17 | navigationItem.backBarButtonItem = UIBarButtonItem.backButton
18 | navigationItem.rightBarButtonItem = UIBarButtonItem.skipButton
19 | navigationItem.rightBarButtonItem?.target = self
20 | navigationItem.rightBarButtonItem?.action = #selector(handleSkipTapped)
21 | let nextButton = UIButton(title: NSLocalizedString("Next", comment: "Next button title"), font: .onboardingFont)
22 | nextButton.addTarget(self, action: #selector(handleNextTapped), for: .touchUpInside)
23 | view.addSubview(nextButton)
24 | let constraints: [NSLayoutConstraint] = [
25 | nextButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
26 | bottomLayoutGuide.topAnchor.constraint(equalTo: nextButton.bottomAnchor, constant: 10),
27 | ]
28 | nextButton.translatesAutoresizingMaskIntoConstraints = false
29 | NSLayoutConstraint.activate(constraints)
30 | }
31 |
32 | override func viewWillAppear(_ animated: Bool) {
33 | super.viewWillAppear(animated)
34 | let factory: AnimationFactory?
35 | if let backgroundColorProvider = self as? BackgroundColorProvider {
36 | factory = { [unowned backgroundColorProvider] (_, _) in
37 | return backgroundColorProvider.animation
38 | }
39 | }
40 | else {
41 | factory = nil
42 | }
43 | perform(coordinatedAnimations: factory)
44 | }
45 | }
46 |
47 | private extension ActionableViewController {
48 | @objc func handleNextTapped(_ sender: UIButton) {
49 | (navigationController as? BoardingNavigationController)?.pushToNextViewController(animated: true)
50 | }
51 |
52 | @objc func handleSkipTapped(_ sender: UIButton) {
53 | navigationController?.pushViewController(CompletedViewController(), animated: true)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [http://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: http://contributor-covenant.org
74 | [version]: http://contributor-covenant.org/version/1/4/
--------------------------------------------------------------------------------
/BoardingPass/HorizontalSlideAnimatedTransition.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HorizontalSlideAnimatedTransition.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class HorizontalSlideAnimatedTransiton: NSObject {
12 |
13 | enum TransitionType {
14 | case push, pop
15 | }
16 |
17 | let slideType: TransitionType
18 |
19 | #if swift(>=3.0)
20 |
21 | /**
22 | Initializes a HorizontalSlideAnimatedTransiton for handling a pan gesture on a UINavigationController
23 |
24 | - parameter navigationOperation: The the navigation operation bieng animated
25 | */
26 | public init(navigationOperation: UINavigationControllerOperation) {
27 | switch navigationOperation {
28 | case .none, .push:
29 | slideType = .push
30 | case .pop:
31 | slideType = .pop
32 | }
33 | super.init()
34 | }
35 | #else
36 |
37 | /**
38 | Initializes a HorizontalSlideAnimatedTransiton for handling a pan gesture on a UINavigationController
39 |
40 | - parameter navigationOperation: The the navigation operation bieng animated
41 | */
42 | public init(navigationOperation: UINavigationControllerOperation) {
43 | switch navigationOperation {
44 | case .None, .Push:
45 | slideType = .push
46 | case .Pop:
47 | slideType = .pop
48 | }
49 | super.init()
50 | }
51 | #endif
52 |
53 | }
54 |
55 | extension HorizontalSlideAnimatedTransiton: UIViewControllerAnimatedTransitioning {
56 |
57 | public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
58 |
59 | guard let presented = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey),
60 | let presenting = transitionContext.viewController(forKey: UITransitionContextFromViewControllerKey) else {
61 | transitionContext.completeTransition(false)
62 | return
63 | }
64 |
65 | // Optional for backward compatibility
66 | let container: UIView? = transitionContext.containerView
67 |
68 | container?.addSubview(presented.view)
69 | let width: CGFloat
70 | switch slideType {
71 | case .push:
72 | width = container?.frame.width ?? 0
73 | case .pop:
74 | width = -(container?.frame.width ?? 0)
75 | }
76 | presented.view.transform = CGAffineTransform(translationX: width, y: 0)
77 | let animations = {
78 | presenting.view.transform = CGAffineTransform(translationX: -width, y: 0)
79 | presented.view.transform = CGAffineTransform.identity
80 | }
81 | let completion = { (completed: Bool) in
82 | if completed {
83 | presented.view.transform = CGAffineTransform.identity
84 | }
85 | else {
86 | presenting.view.transform = CGAffineTransform.identity
87 | }
88 | transitionContext.completeTransition(completed)
89 | }
90 | UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0,
91 | options: [.beginFromCurrentState],
92 | animations: animations, completion: completion)
93 | }
94 |
95 | public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
96 | return 0.4
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/BoardingPass.xcodeproj/xcshareddata/xcschemes/BoardingPass.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 |
--------------------------------------------------------------------------------
/BoardingPass/BoardingInformation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BoardingInformation.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol BoardingInformation {
12 |
13 | /// Used to determine the next view controller to push in the stack, a nil value means there is no next view,
14 | /// so no swipe left for next gesture will be allowed
15 | var nextViewController: UIViewController? { get }
16 | /// Used to determine the previous view controller to pop to, the default value of the previous view controller
17 | /// in the navigation stack. A nil value will explicitly disable the swipe right for previous view gesture.
18 | var previousViewController: UIViewController? { get }
19 |
20 | }
21 |
22 | #if swift(>=3.0)
23 | public typealias AnimationFactory = (_ container: UIViewController?, _ animated: Bool) -> (() -> Void)
24 | public typealias ContextualAnimation = (_ context: UIViewControllerTransitionCoordinatorContext) -> Void
25 | #else
26 | public typealias AnimationFactory = (UIViewController?, Bool) -> (() -> Void)
27 | public typealias ContextualAnimation = (UIViewControllerTransitionCoordinatorContext) -> Void
28 | #endif
29 |
30 | public extension UIViewController {
31 |
32 | /**
33 | A function for handling an animation that may or may not be performed alongside an animation context
34 |
35 | - parameter animation: A closure that takes a view controller and an animated flag and returns an animation block
36 | to perform perform, either alongside a context if one exists, with a fallback of applying
37 | it to the view
38 | - parameter completion: A closure that takes a view controller and an animated flag, and returns an animation block
39 | to perform alongside a context, with a fallback of applying it to the view
40 | - parameter cancellation: A cancellation action to handle restoration of any state that isn't properly rolled back
41 | if the animation block is cancelled
42 | */
43 | final public func perform(coordinatedAnimations animation: AnimationFactory? = nil,
44 | completion: AnimationFactory? = nil,
45 | cancellation: ContextualAnimation? = nil) {
46 | let parentController = self.parent
47 | let animationInContext: ContextualAnimation = { (context: UIViewControllerTransitionCoordinatorContext) in
48 | animation?(parentController, context.isAnimated)()
49 | }
50 | let completionInContext = { (context: UIViewControllerTransitionCoordinatorContext) in
51 | if context.isCancelled {
52 | cancellation?(context)
53 | }
54 | else {
55 | completion?(parentController, context.isAnimated)()
56 | }
57 | }
58 | if let coordinator = transitionCoordinator {
59 | coordinator.animateAlongsideTransition(in: parent?.view, animation: animationInContext, completion: completionInContext)
60 | }
61 | else {
62 | animation?(parentController, false)()
63 | completion?(parentController, false)()
64 | }
65 | }
66 | }
67 |
68 | public extension BoardingInformation {
69 |
70 | var nextViewController: UIViewController? {
71 | return nil
72 | }
73 | var previousViewController: UIViewController? {
74 | guard let viewController = self as? UIViewController else {
75 | return nil
76 | }
77 | return viewController.navigationController?.viewController(beforeController: viewController)
78 | }
79 |
80 | var allowGestures: Bool {
81 | return true
82 | }
83 |
84 | }
85 |
86 | private extension UINavigationController {
87 |
88 | func viewController(beforeController viewController: UIViewController) -> UIViewController? {
89 | guard let index = viewControllers.index(of: viewController) else {
90 | return nil
91 | }
92 | guard index > 0 else {
93 | return nil
94 | }
95 | #if swift(>=3.0)
96 | return viewControllers[index.advanced(by: -1)]
97 | #else
98 | return viewControllers[index.predecessor()]
99 | #endif
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/BoardingPassExample/Onboarding Demo/OnboardingWrapperViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OnboardingNavigationViewController.swift
3 | // BoardingPassExample
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import BoardingPass
10 |
11 | extension UIFont {
12 | static let onboardingFont: UIFont = UIFont.systemFont(ofSize: 26.0)
13 | }
14 |
15 | protocol BackgroundColorProvider: class {
16 |
17 | weak var onboardingDelegate: OnboardingViewControllerDelegate? { get set }
18 | var backgroundColor: UIColor { get }
19 | var currentProgress: Progress { get }
20 |
21 | }
22 |
23 | extension BackgroundColorProvider {
24 |
25 | var animation: (() -> Void) {
26 | return { [unowned self] in
27 | self.onboardingDelegate?.backgroundColor = self.backgroundColor
28 | self.onboardingDelegate?.progress = self.currentProgress
29 | }
30 | }
31 |
32 | }
33 |
34 | protocol OnboardingViewControllerDelegate: class {
35 |
36 | var backgroundColor: UIColor? { get set }
37 | var progress: Progress { get set }
38 |
39 | }
40 |
41 | class OnboardingNavigationViewController: BoardingNavigationController, OnboardingViewControllerDelegate {
42 |
43 | // We're creating a non-standard progress slider because the UIProgressView
44 | // has a visual glitch when the animation is cancelled, probably due to
45 | // CALayer animations
46 | let progressSlider = UIView()
47 | var progress = Progress() {
48 | didSet {
49 | let progressAmount = CGFloat(progress.fractionCompleted)
50 | var newTransform = CGAffineTransform.identity
51 | newTransform = newTransform.translatedBy(x: (-view.frame.width + (view.frame.width * progressAmount)) / 2, y: 0)
52 | newTransform = newTransform.scaledBy(x: progressAmount, y: 1)
53 | progressSlider.transform = newTransform
54 | }
55 | }
56 |
57 | var backgroundColor: UIColor? {
58 | get {
59 | return view.backgroundColor
60 | }
61 | set {
62 | view.backgroundColor = newValue
63 | }
64 | }
65 |
66 | static func sampleOnboarding() -> BoardingNavigationController {
67 | let viewControllers = [
68 | FirstViewController(),
69 | SecondViewController(),
70 | ThirdViewController(),
71 | ]
72 | let onboarding = OnboardingNavigationViewController(viewControllersToPresent: viewControllers)
73 | return onboarding
74 | }
75 |
76 | func beginOnboarding() {
77 | let viewControllers = [UIColor.red, UIColor.green, UIColor.blue].map { color -> UIViewController in
78 | let viewController = UIViewController()
79 | viewController.view.backgroundColor = color
80 | return viewController
81 | }
82 | let onboarding = BoardingNavigationController(viewControllersToPresent: viewControllers)
83 | present(onboarding, animated: true, completion: nil)
84 | }
85 |
86 | override func viewDidLoad() {
87 | super.viewDidLoad()
88 | navigationBar.addSubview(progressSlider)
89 | progressSlider.frame.size.height = 4
90 | progressSlider.frame.size.width = navigationBar.frame.width
91 | progressSlider.frame.origin.x = navigationBar.frame.origin.x
92 | progressSlider.frame.origin.y = navigationBar.frame.maxY - progressSlider.frame.height
93 | progressSlider.backgroundColor = .red
94 | view.backgroundColor = UIColor.white
95 | }
96 |
97 | override func pushViewController(_ viewController: UIViewController, animated: Bool) {
98 | super.pushViewController(viewController, animated: animated)
99 | (viewController as? BackgroundColorProvider)?.onboardingDelegate = self
100 | }
101 |
102 | override func popViewController(animated: Bool) -> UIViewController? {
103 | let viewController = super.popViewController(animated: animated)
104 | (viewController as? BackgroundColorProvider)?.onboardingDelegate = self
105 | return viewController
106 | }
107 |
108 | override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
109 | let poppedViewControllers = super.popToViewController(viewController, animated: animated)
110 | (viewController as? BackgroundColorProvider)?.onboardingDelegate = self
111 | return poppedViewControllers
112 | }
113 |
114 | override func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) {
115 | super.setViewControllers(viewControllers, animated: animated)
116 | for viewController in viewControllers {
117 | (viewController as? BackgroundColorProvider)?.onboardingDelegate = self
118 | }
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/BoardingPass/BoardingPassCompatibility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BoardingPassCompatibility.swift
3 | // BoardingPass
4 | //
5 | // Created by Adam Tierney on 9/19/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | #if swift(>=3.0)
12 |
13 | let UITransitionContextToViewControllerKey: UITransitionContextViewControllerKey = UITransitionContextViewControllerKey.to
14 | let UITransitionContextFromViewControllerKey: UITransitionContextViewControllerKey = UITransitionContextViewControllerKey.from
15 |
16 | #else
17 |
18 | extension UIViewController {
19 | @nonobjc var parent: UIViewController? {
20 | return parentViewController
21 | }
22 |
23 | @nonobjc var transitionCoordinator: UIViewControllerTransitionCoordinator? {
24 | return transitionCoordinator()
25 | }
26 | }
27 |
28 | // MARK: - Animations
29 |
30 | extension UIViewAnimationOptions {
31 | @nonobjc static var beginFromCurrentState = UIViewAnimationOptions.BeginFromCurrentState
32 | }
33 |
34 | extension UIView {
35 | @nonobjc class func animate(withDuration duration: NSTimeInterval, delay: NSTimeInterval, options: UIViewAnimationOptions, animations: () -> Void, completion: ((Bool) -> Void)?) {
36 | animateWithDuration(duration, delay: delay, options: options, animations: animations, completion: completion)
37 | }
38 | }
39 |
40 | // MARK: - Transitions
41 |
42 | extension UIViewControllerContextTransitioning {
43 |
44 | func viewController(forKey key: String) -> UIViewController? {
45 | return viewControllerForKey(key)
46 | }
47 |
48 | var containerView: UIView? {
49 | return containerView()
50 | }
51 | }
52 |
53 | public typealias TimeInterval = NSTimeInterval
54 | extension HorizontalSlideAnimatedTransiton {
55 |
56 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
57 | animateTransition(using: transitionContext)
58 | }
59 |
60 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
61 | return transitionDuration(using: transitionContext)
62 | }
63 |
64 | }
65 |
66 | extension UIViewControllerTransitionCoordinator {
67 | func animateAlongsideTransition(in view: UIView?,
68 | animation theAnimation: ( (UIViewControllerTransitionCoordinatorContext) -> Void)?,
69 | completion: ((UIViewControllerTransitionCoordinatorContext) -> Void)? = nil) -> Bool {
70 | return animateAlongsideTransitionInView(view, animation: theAnimation, completion: completion)
71 | }
72 | }
73 |
74 | extension UIViewControllerTransitionCoordinatorContext {
75 | @nonobjc var isAnimated: Bool {
76 | return isAnimated()
77 | }
78 |
79 | @nonobjc var isCancelled: Bool {
80 | return isCancelled()
81 | }
82 | }
83 |
84 | extension UIPercentDrivenInteractiveTransition {
85 | @nonobjc func cancel() {
86 | cancelInteractiveTransition()
87 | }
88 |
89 | @nonobjc func update(percentComplete: CGFloat) {
90 | updateInteractiveTransition(percentComplete)
91 | }
92 |
93 | @nonobjc func finish() {
94 | finishInteractiveTransition()
95 | }
96 | }
97 |
98 | extension UIPanGestureRecognizer {
99 | @nonobjc var isEnabled: Bool {
100 | set(newVal) {
101 | enabled = newVal
102 | }
103 | get {
104 | return enabled
105 | }
106 | }
107 |
108 | @nonobjc func translation(in view: UIView?) -> CGPoint {
109 | return translationInView(view)
110 | }
111 |
112 | @nonobjc func velocity(in view: UIView?) -> CGPoint {
113 | return velocityInView(view)
114 | }
115 | }
116 |
117 | // MARK: - Transform
118 |
119 | extension CGAffineTransform {
120 | @nonobjc static let identity: CGAffineTransform = CGAffineTransformIdentity
121 |
122 | init(translationX: CGFloat, y: CGFloat) {
123 | self = CGAffineTransformMakeTranslation(translationX, y)
124 | }
125 | }
126 |
127 | // MARK: - Dispatch
128 |
129 | struct DispatchQueue {
130 | @nonobjc static var main = DispatchQueue()
131 | func async(work: () -> Swift.Void) {
132 | dispatch_async(dispatch_get_main_queue(), {
133 | work()
134 | })
135 | }
136 | }
137 |
138 | // MARK: - Array
139 |
140 | extension Array where Element: Equatable {
141 |
142 | func index(of element: Element) -> Int? {
143 | return indexOf(element)
144 | }
145 |
146 | mutating func insert(newElement: Element, at: Int) {
147 | insert(newElement, atIndex: at)
148 | }
149 |
150 | }
151 |
152 | #endif
153 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BoardingPass
2 | > Navigate Your View Stack with Interactive Swipe Gestures
3 |
4 | [](https://travis-ci.org/Raizlabs/BoardingPass)
5 | [](http://cocoapods.org/pods/BoardingPass)
6 | [](http://cocoapods.org/pods/BoardingPass)
7 | [](http://cocoapods.org/pods/BoardingPass)
8 | [](https://github.com/Carthage/Carthage)
9 |
10 | BoardingPass is a subclass of `UINavigationController` with interactive push and pop gestures. It offers behaviors similar to `UIPageViewController`, but with all of the familiar behaviors of navigation controllers, and the ability to easily animate property changes alongside the transitions.
11 |
12 | 
13 |
14 | ## Features
15 |
16 | - [x] Interactive swipe and pan transitions
17 | - [x] Navigation Controller push and pop use slide animation as well
18 | - [x] Supports animating other properties alongside the transition
19 | - [x] Fine grained control over when the push and pop gestures should be active.
20 |
21 | ## Requirements
22 |
23 | - iOS 9.0+
24 | - Xcode 8.0+
25 |
26 | ## Installation with CocoaPods
27 |
28 | BoardingPass is available through [CocoaPods](http://cocoapods.org). To install
29 | it, simply add the following line to your Podfile:
30 |
31 | ```ruby
32 | pod 'BoardingPass'
33 | ```
34 |
35 | ## Installation with Carthage
36 | Create a `Cartfile` that lists the framework and run `carthage update`. Follow the [instructions](https://github.com/Carthage/Carthage#if-youre-building-for-ios) to add `$(SRCROOT)/Carthage/Build/iOS/BoardingPass.framework` to an iOS project.
37 |
38 | ```ogdl
39 | github "Raizlabs/BoardingPass"
40 | ```
41 |
42 | #### Manually
43 | 1. Download all of the `.swift` files in `BoardingPass/` and drop them into your project.
44 | 2. Congratulations!
45 |
46 | ## Usage example
47 |
48 | To see a complete example of using the gallery, take a look at the [sample project](https://github.com/Raizlabs/BoardingPass/blob/develop/BoardingPassExample/Onboarding%20Demo/OnboardingWrapperViewController.swift).
49 |
50 | ### Simple Boarding
51 |
52 | At it's simplest, a `BoardingNavigationController` can be initialized with an array of view controllers, and that will allow the user to swipe forward and backward through the navigation stack.
53 |
54 | ```swift
55 | func beginOnboarding() {
56 | let viewControllers = [
57 | FirstViewController(),
58 | SecondViewController(),
59 | ThirdViewController(),
60 | ]
61 | let onboarding = BoardingNavigationController(viewControllersToPresent: viewControllers)
62 | present(onboarding, animated: true, completion: nil)
63 | }
64 | ```
65 |
66 | ### Controlling Navigation
67 |
68 | For finer grained control over navigation, for instance to now allow the user to page backward after viewing the complete boarding stack, a view controller can conform to the `BoardingInformation` protocol and set a value for `nextViewController` or `previousViewController`.
69 |
70 | ```swift
71 | extension ThirdViewController: BoardingInformation {
72 |
73 | var nextViewController: UIViewController? {
74 | let completed = CompletedViewController()
75 | return completed
76 | }
77 |
78 | }
79 | ```
80 |
81 | By returning a view controller outside of the series of view controllers to present, the `BoardingNavigationController` will disable the swipe gestures once the user advances to the `CompletedViewController`.
82 |
83 | ### Going Above and Beyond
84 |
85 | To give the boarding stack a more custom look and feel, `BoadingPass` is designed to make it easy to add animations that run alongside the push and pop presentations. To add a progress slider and a background color alongside navigation animations.
86 |
87 | The first step is defining a protocol that each of the presented view controllers is going to conform to, and a delegate protocol that the BoardingInformation subclass is going to conform to to allow the view controllers to communicate back up to the container.
88 |
89 | ```swift
90 | protocol BackgroundColorProvider: class {
91 |
92 | weak var onboardingDelegate: OnboardingViewControllerDelegate? { get set }
93 | var backgroundColor: UIColor { get }
94 | var currentProgress: Progress { get }
95 |
96 | }
97 | ```
98 |
99 | ```swift
100 | protocol OnboardingViewControllerDelegate: class {
101 |
102 | var backgroundColor: UIColor? { get set }
103 | var progress: Progress { get set }
104 |
105 | }
106 | ```
107 |
108 | Next the `BackgroundColorProvider` can be extended to create a shared function the generate closure to animate the background color and progress indicator.
109 |
110 | ```
111 | extension BackgroundColorProvider {
112 |
113 | var animation: (() -> Void) {
114 | return { [unowned self] in
115 | self.onboardingDelegate?.backgroundColor = self.backgroundColor
116 | self.onboardingDelegate?.progress = self.currentProgress
117 | }
118 | }
119 |
120 | }
121 | ```
122 |
123 | Then each class implementing `BackgroundColorProvider` needs to add a method to `viewWillAppear` to perform the coordinated animation alongside the current context, with a fallback of executing the animation if there is no context.
124 |
125 | ```swift
126 | override func viewWillAppear(_ animated: Bool) {
127 | super.viewWillAppear(animated)
128 | let factory: AnimationFactory = { [unowned self] (_, _) in
129 | return self.animation
130 | }
131 | perform(coordinatedAnimations: factory)
132 | }
133 | ```
134 |
135 | ## Contributing
136 |
137 | Issues and pull requests are welcome! Please ensure that you have the latest [SwiftLint](https://github.com/realm/SwiftLint) installed before committing and that there are no style warnings generated when building.
138 |
139 | Contributors are expected to abide by the [Contributor Covenant Code of Conduct](https://github.com/Raizlabs/BoardingPass/blob/develop/CONTRIBUTING.md).
140 |
141 | ## License
142 |
143 | BoardingPass is available under the MIT license. See the LICENSE file for more info.
144 |
145 | ## Author
146 |
147 | Michael Skiba, [@atelierclkwrk](https://twitter.com/atelierclkwrk)
148 |
--------------------------------------------------------------------------------
/BoardingPass/BoardingNavigationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BoardingNavigationController.swift
3 | // BoardingPass
4 | //
5 | // Created by Michael Skiba on 7/20/16.
6 | // Copyright © 2016 Raizlabs. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct TransitionState {
12 | enum Direction {
13 | case push
14 | case pop
15 | case none
16 | }
17 |
18 | var direction: Direction = .none
19 | var previousState: [UIViewController]?
20 |
21 | init(direction: Direction, previousState: [UIViewController]) {
22 | self.direction = direction
23 | self.previousState = previousState
24 | }
25 |
26 | init() {
27 | direction = .none
28 | previousState = nil
29 | }
30 | }
31 |
32 | // MARK: - Core
33 |
34 | #if swift(>=3.0)
35 |
36 | open class BoardingNavigationController: UINavigationController {
37 |
38 | let panGestureRecognizer = UIPanGestureRecognizer()
39 | var transitionState = TransitionState()
40 | var interactionController: UIPercentDrivenInteractiveTransition?
41 |
42 | /// An array of view controllers used to determine the next or previous view
43 | /// controller to present in the series. These are ignored if the top view
44 | /// controller conforms to `BoardingInformation`
45 | open var viewControllersToPresent: [UIViewController] = []
46 |
47 | /**
48 | An optional closure that takes a `UINavigationControllerOperation` and returns a
49 | `UIViewControllerAnimatedTransitioning` object. Used to allow customization of
50 | the animation. The default value is `HorizontalSlideAnimatedTransiton.init`.
51 | Setting this value to `nil` will default to the standard navigation controller
52 | animation.
53 | */
54 | open var animatedTransitioningProvider: ((UINavigationControllerOperation) -> UIViewControllerAnimatedTransitioning)? = HorizontalSlideAnimatedTransiton.init
55 |
56 | open override func viewDidLoad() {
57 | super.viewDidLoad()
58 | delegate = self
59 | configure(gestureRecognizer: panGestureRecognizer, action: #selector(handlePan))
60 | }
61 | }
62 |
63 | #else
64 |
65 | public class BoardingNavigationController: UINavigationController {
66 |
67 | let panGestureRecognizer = UIPanGestureRecognizer()
68 | var transitionState = TransitionState()
69 | var interactionController: UIPercentDrivenInteractiveTransition?
70 |
71 | /// An array of view controllers used to determine the next or previous view
72 | /// controller to present in the series. These are ignored if the top view
73 | /// controller conforms to `BoardingInformation`
74 | public var viewControllersToPresent: [UIViewController] = []
75 |
76 | /**
77 | An optional closure that takes a `UINavigationControllerOperation` and returns a
78 | `UIViewControllerAnimatedTransitioning` object. Used to allow customization of
79 | the animation. The default value is `HorizontalSlideAnimatedTransiton.init`.
80 | Setting this value to `nil` will default to the standard navigation controller
81 | animation.
82 | */
83 | public var animatedTransitioningProvider: ((UINavigationControllerOperation) -> UIViewControllerAnimatedTransitioning)? = HorizontalSlideAnimatedTransiton.init
84 |
85 | public override func viewDidLoad() {
86 | super.viewDidLoad()
87 | delegate = self
88 | configure(gestureRecognizer: panGestureRecognizer, action: #selector(handlePan))
89 | }
90 | }
91 |
92 | #endif
93 |
94 | // MARK: - Navigation Delegate
95 |
96 | #if swift(>=3.0)
97 |
98 | extension BoardingNavigationController: UINavigationControllerDelegate {
99 |
100 | public func navigationController(_ navigationController: UINavigationController,
101 | animationControllerFor operation: UINavigationControllerOperation,
102 | from fromVC: UIViewController,
103 | to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
104 | return animatedTransitioningProvider?(operation)
105 | }
106 |
107 | public func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
108 | return interactionController
109 | }
110 | }
111 |
112 | #else
113 |
114 | extension BoardingNavigationController: UINavigationControllerDelegate {
115 | public func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
116 | return animatedTransitioningProvider?(operation)
117 | }
118 |
119 | public func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
120 | return interactionController
121 | }
122 | }
123 |
124 | #endif
125 |
126 | public extension BoardingNavigationController {
127 | /**
128 | Initializes the `BoardingNavigationController` with a populated array of
129 | view controllers to present. If the array is non-empty then it also sets
130 | the root view controller to the first element in the array.
131 |
132 | - parameter viewControllersToPresent: The array of view controllers to use
133 | as default navigation options.
134 | */
135 | public convenience init(viewControllersToPresent: [UIViewController]) {
136 | if let firstViewController = viewControllersToPresent.first {
137 | self.init(rootViewController: firstViewController)
138 | }
139 | else {
140 | self.init()
141 | }
142 | self.viewControllersToPresent = viewControllersToPresent
143 | }
144 |
145 | /**
146 | Pushes the next view controller in boarding pass stack if one exists.
147 |
148 | - parameter animated: Specify true to animate the transition or false
149 | if you do not want the transition to be animated.
150 | */
151 | public func pushToNextViewController(animated isAnimated: Bool) {
152 | if let pushableViewController = topViewController.flatMap(boardingInfo(afterController:)) {
153 | pushViewController(pushableViewController, animated: isAnimated)
154 | }
155 | }
156 |
157 | /**
158 | Pops to the previous view controller in the boarding pass stack if one exists.
159 |
160 | - parameter animated: Specify true to animate the transition or false
161 | if you do not want the transition to be animated.
162 | */
163 | public func popToPreviousViewController(animated isAnimated: Bool) {
164 | if let poppableViewController = topViewController.flatMap(boardingInfo(afterController:)) {
165 | popToAndInsertIfNeeded(poppableViewController, animated: isAnimated)
166 | }
167 | }
168 | }
169 |
170 | // MARK: - Extensions
171 |
172 | // MARK: Actions
173 | private extension BoardingNavigationController {
174 |
175 | #if swift(>=3.0)
176 | func popToAndInsertIfNeeded(_ viewController: UIViewController, animated: Bool) {
177 | if !viewControllers.contains(viewController) {
178 | if viewControllers.count > 1 {
179 | viewControllers.insert(viewController,
180 | at: ((viewControllers.endIndex - 1) - 1))
181 | }
182 | else {
183 | viewControllers.insert(viewController, at: viewControllers.startIndex)
184 | }
185 | }
186 | popToViewController(viewController, animated: animated)
187 | }
188 | #else
189 | func popToAndInsertIfNeeded(viewController: UIViewController, animated: Bool) {
190 | if !viewControllers.contains(viewController) {
191 | if viewControllers.count > 1 {
192 | viewControllers.insert(viewController,
193 | at: ((viewControllers.endIndex - 1) - 1))
194 | }
195 | else {
196 | viewControllers.insert(viewController, at: viewControllers.startIndex)
197 | }
198 | }
199 | popToViewController(viewController, animated: animated)
200 | }
201 | #endif
202 |
203 | #if swift(>=3.0)
204 | @objc func handlePan(from sender: UIPanGestureRecognizer) {
205 | switch sender.state {
206 | case .began, .possible:
207 | break
208 | case .changed:
209 | updateAnimation(forRecognizer: sender)
210 | case .ended, .failed, .cancelled:
211 | finishAnimation(forRecognizer: sender)
212 | }
213 | }
214 | #else
215 | @objc func handlePan(from sender: UIPanGestureRecognizer) {
216 | switch sender.state {
217 | case .Began, .Possible:
218 | break
219 | case .Changed:
220 | updateAnimation(forRecognizer: sender)
221 | case .Ended, .Failed, .Cancelled:
222 | finishAnimation(forRecognizer: sender)
223 | }
224 | }
225 | #endif
226 | }
227 |
228 | private extension BoardingNavigationController {
229 |
230 | func viewController(before viewController: UIViewController?) -> UIViewController? {
231 | guard let vc = viewController else {
232 | return nil
233 | }
234 | guard let index = viewControllersToPresent.index(of: vc) else {
235 | return nil
236 | }
237 | guard index > 0 else {
238 | return nil
239 | }
240 |
241 | return viewControllersToPresent[(index - 1)]
242 | }
243 |
244 | func viewController(after viewController: UIViewController?) -> UIViewController? {
245 | guard let vc = viewController else {
246 | return nil
247 | }
248 | guard let index = ((viewControllersToPresent.index(of: vc))) else {
249 | return nil
250 | }
251 |
252 | let adjustedIndex = index + 1
253 |
254 | guard adjustedIndex < viewControllersToPresent.count else {
255 | return nil
256 | }
257 |
258 | return viewControllersToPresent[adjustedIndex]
259 | }
260 |
261 | func updateAnimation(forRecognizer recognizer: UIPanGestureRecognizer) {
262 | let xTranslation = recognizer.translation(in: view).x
263 | let percent = xTranslation / view.frame.width
264 | if (percent < 0 && transitionState.direction == .pop) ||
265 | (percent > 0 && transitionState.direction == .push) {
266 | return
267 | }
268 | if (percent > 0.66 && transitionState.direction == .pop) ||
269 | (percent < -0.66 && transitionState.direction == .push) {
270 | recognizer.isEnabled = false
271 | return
272 | }
273 | if interactionController == nil {
274 | interactionController = UIPercentDrivenInteractiveTransition()
275 | }
276 | // The transitioning delegate being nil tells us that there isn't another active transition in play
277 | if transitionState.direction == .none && transitioningDelegate == nil {
278 | if xTranslation < 0 {
279 | guard let pushableViewControler = topViewController.flatMap(boardingInfo(afterController:)) else {
280 | return
281 | }
282 | transitionState = TransitionState(direction: .push, previousState: viewControllers)
283 | pushViewController(pushableViewControler, animated: true)
284 | }
285 | else if xTranslation > 0 {
286 | guard let poppableViewController = topViewController.flatMap(boardingInfo(beforeController:)) else {
287 | return
288 | }
289 | transitionState = TransitionState(direction: .pop, previousState: viewControllers)
290 | popToAndInsertIfNeeded(poppableViewController, animated: true)
291 | }
292 | }
293 | interactionController?.update(abs(percent))
294 | }
295 |
296 | func boardingInfo(beforeController viewController: UIViewController) -> UIViewController? {
297 | let poppableViewController: UIViewController?
298 | if let boardingViewController = viewController as? BoardingInformation {
299 | poppableViewController = boardingViewController.previousViewController
300 | }
301 | else {
302 | poppableViewController = self.viewController(before: viewController)
303 | }
304 | return poppableViewController
305 | }
306 |
307 | func boardingInfo(afterController viewController: UIViewController) -> UIViewController? {
308 | let pushableViewControler: UIViewController?
309 | if let boardingViewController = viewController as? BoardingInformation {
310 | pushableViewControler = boardingViewController.nextViewController
311 | }
312 | else {
313 | pushableViewControler = self.viewController(after: viewController)
314 | }
315 | return pushableViewControler
316 | }
317 |
318 | func finishAnimation(forRecognizer recognizer: UIPanGestureRecognizer) {
319 | recognizer.isEnabled = true
320 | let rawVelocity = recognizer.velocity(in: view).x
321 | let velocityPercentPerSecond: CGFloat
322 | switch transitionState.direction {
323 | case .pop:
324 | velocityPercentPerSecond = rawVelocity / view.frame.width
325 | case .push:
326 | velocityPercentPerSecond = -rawVelocity / view.frame.width
327 | case .none:
328 | velocityPercentPerSecond = 0
329 | }
330 | let percentComplete = interactionController?.percentComplete ?? 0
331 | if percentComplete > 0.5 || percentComplete + velocityPercentPerSecond > 0.75 {
332 | interactionController?.finish()
333 | interactionController = nil
334 | transitionState = TransitionState()
335 | }
336 | else {
337 | cleanUpAnimation()
338 | }
339 | }
340 |
341 | func cleanUpAnimation() {
342 | interactionController?.cancel()
343 | if let previousState = transitionState.previousState {
344 | viewControllers = previousState
345 | }
346 | interactionController = nil
347 | DispatchQueue.main.async {
348 | self.transitionState = TransitionState()
349 | }
350 | }
351 |
352 | func configure(gestureRecognizer recognizer: UIGestureRecognizer, action: Selector) {
353 | recognizer.addTarget(self, action: action)
354 | view.addGestureRecognizer(recognizer)
355 | }
356 | }
357 |
358 | private extension UISwipeGestureRecognizer {
359 | convenience init(direction: UISwipeGestureRecognizerDirection) {
360 | self.init()
361 | self.direction = direction
362 | }
363 | }
364 |
--------------------------------------------------------------------------------
/BoardingPass.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 23A09E271D908D05004A9ADF /* BoardingPassCompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23A09E261D908D05004A9ADF /* BoardingPassCompatibility.swift */; };
11 | 7264CA211D3FC4AB00033FC4 /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA201D3FC4AB00033FC4 /* FirstViewController.swift */; };
12 | 7264CA231D3FC4B300033FC4 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA221D3FC4B300033FC4 /* SecondViewController.swift */; };
13 | 7264CA251D3FC4B900033FC4 /* ThirdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA241D3FC4B900033FC4 /* ThirdViewController.swift */; };
14 | 7264CA261D3FC54A00033FC4 /* BoardingPass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72BE8D661D3EC55E005720FB /* BoardingPass.framework */; };
15 | 7264CA271D3FC54A00033FC4 /* BoardingPass.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 72BE8D661D3EC55E005720FB /* BoardingPass.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
16 | 7264CA2C1D3FC69800033FC4 /* BoardingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA2B1D3FC69800033FC4 /* BoardingNavigationController.swift */; };
17 | 7264CA2E1D3FEB2A00033FC4 /* BoardingInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA2D1D3FEB2A00033FC4 /* BoardingInformation.swift */; };
18 | 7264CA331D3FEC4C00033FC4 /* CompletedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA321D3FEC4C00033FC4 /* CompletedViewController.swift */; };
19 | 7264CA351D4001BD00033FC4 /* HorizontalSlideAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7264CA341D4001BD00033FC4 /* HorizontalSlideAnimatedTransition.swift */; };
20 | 72BE8D6A1D3EC55E005720FB /* BoardingPass.h in Headers */ = {isa = PBXBuildFile; fileRef = 72BE8D691D3EC55E005720FB /* BoardingPass.h */; settings = {ATTRIBUTES = (Public, ); }; };
21 | 72BE8D781D3FBC05005720FB /* BoardingPassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72BE8D771D3FBC05005720FB /* BoardingPassTests.swift */; };
22 | 72BE8D7A1D3FBC05005720FB /* BoardingPass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72BE8D661D3EC55E005720FB /* BoardingPass.framework */; };
23 | 72BE8D871D3FBCDE005720FB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72BE8D861D3FBCDE005720FB /* AppDelegate.swift */; };
24 | 72BE8D891D3FBCDE005720FB /* OnboardingWrapperViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72BE8D881D3FBCDE005720FB /* OnboardingWrapperViewController.swift */; };
25 | 72BE8D8E1D3FBCDE005720FB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 72BE8D8D1D3FBCDE005720FB /* Assets.xcassets */; };
26 | 72BE8D911D3FBCDE005720FB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 72BE8D8F1D3FBCDE005720FB /* LaunchScreen.storyboard */; };
27 | 72F163451D4910D1007D983B /* ActionableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F163441D4910D1007D983B /* ActionableViewController.swift */; };
28 | /* End PBXBuildFile section */
29 |
30 | /* Begin PBXContainerItemProxy section */
31 | 7264CA281D3FC54A00033FC4 /* PBXContainerItemProxy */ = {
32 | isa = PBXContainerItemProxy;
33 | containerPortal = 72BE8D5D1D3EC55E005720FB /* Project object */;
34 | proxyType = 1;
35 | remoteGlobalIDString = 72BE8D651D3EC55E005720FB;
36 | remoteInfo = BoardingPass;
37 | };
38 | 72BE8D7B1D3FBC05005720FB /* PBXContainerItemProxy */ = {
39 | isa = PBXContainerItemProxy;
40 | containerPortal = 72BE8D5D1D3EC55E005720FB /* Project object */;
41 | proxyType = 1;
42 | remoteGlobalIDString = 72BE8D651D3EC55E005720FB;
43 | remoteInfo = BoardingPass;
44 | };
45 | /* End PBXContainerItemProxy section */
46 |
47 | /* Begin PBXCopyFilesBuildPhase section */
48 | 7264CA2A1D3FC54A00033FC4 /* Embed Frameworks */ = {
49 | isa = PBXCopyFilesBuildPhase;
50 | buildActionMask = 2147483647;
51 | dstPath = "";
52 | dstSubfolderSpec = 10;
53 | files = (
54 | 7264CA271D3FC54A00033FC4 /* BoardingPass.framework in Embed Frameworks */,
55 | );
56 | name = "Embed Frameworks";
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | /* End PBXCopyFilesBuildPhase section */
60 |
61 | /* Begin PBXFileReference section */
62 | 23A09E261D908D05004A9ADF /* BoardingPassCompatibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoardingPassCompatibility.swift; sourceTree = ""; };
63 | 7264CA201D3FC4AB00033FC4 /* FirstViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = ""; };
64 | 7264CA221D3FC4B300033FC4 /* SecondViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; };
65 | 7264CA241D3FC4B900033FC4 /* ThirdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThirdViewController.swift; sourceTree = ""; };
66 | 7264CA2B1D3FC69800033FC4 /* BoardingNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoardingNavigationController.swift; sourceTree = ""; };
67 | 7264CA2D1D3FEB2A00033FC4 /* BoardingInformation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoardingInformation.swift; sourceTree = ""; };
68 | 7264CA321D3FEC4C00033FC4 /* CompletedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompletedViewController.swift; sourceTree = ""; };
69 | 7264CA341D4001BD00033FC4 /* HorizontalSlideAnimatedTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalSlideAnimatedTransition.swift; sourceTree = ""; };
70 | 72BE8D661D3EC55E005720FB /* BoardingPass.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoardingPass.framework; sourceTree = BUILT_PRODUCTS_DIR; };
71 | 72BE8D691D3EC55E005720FB /* BoardingPass.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BoardingPass.h; sourceTree = ""; };
72 | 72BE8D6B1D3EC55E005720FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
73 | 72BE8D751D3FBC05005720FB /* BoardingPassTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BoardingPassTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
74 | 72BE8D771D3FBC05005720FB /* BoardingPassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoardingPassTests.swift; sourceTree = ""; };
75 | 72BE8D791D3FBC05005720FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
76 | 72BE8D841D3FBCDE005720FB /* BoardingPassExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BoardingPassExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
77 | 72BE8D861D3FBCDE005720FB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
78 | 72BE8D881D3FBCDE005720FB /* OnboardingWrapperViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingWrapperViewController.swift; sourceTree = ""; };
79 | 72BE8D8D1D3FBCDE005720FB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
80 | 72BE8D901D3FBCDE005720FB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
81 | 72BE8D921D3FBCDE005720FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
82 | 72F163441D4910D1007D983B /* ActionableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionableViewController.swift; sourceTree = ""; };
83 | /* End PBXFileReference section */
84 |
85 | /* Begin PBXFrameworksBuildPhase section */
86 | 72BE8D621D3EC55E005720FB /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | );
91 | runOnlyForDeploymentPostprocessing = 0;
92 | };
93 | 72BE8D721D3FBC05005720FB /* Frameworks */ = {
94 | isa = PBXFrameworksBuildPhase;
95 | buildActionMask = 2147483647;
96 | files = (
97 | 72BE8D7A1D3FBC05005720FB /* BoardingPass.framework in Frameworks */,
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | 72BE8D811D3FBCDE005720FB /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | 7264CA261D3FC54A00033FC4 /* BoardingPass.framework in Frameworks */,
106 | );
107 | runOnlyForDeploymentPostprocessing = 0;
108 | };
109 | /* End PBXFrameworksBuildPhase section */
110 |
111 | /* Begin PBXGroup section */
112 | 7264CA301D3FEC2A00033FC4 /* Process View Controllers */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 7264CA201D3FC4AB00033FC4 /* FirstViewController.swift */,
116 | 7264CA221D3FC4B300033FC4 /* SecondViewController.swift */,
117 | 7264CA241D3FC4B900033FC4 /* ThirdViewController.swift */,
118 | 72F163441D4910D1007D983B /* ActionableViewController.swift */,
119 | );
120 | path = "Process View Controllers";
121 | sourceTree = "";
122 | };
123 | 7264CA311D3FEC4000033FC4 /* Completed View Controller */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 7264CA321D3FEC4C00033FC4 /* CompletedViewController.swift */,
127 | );
128 | path = "Completed View Controller";
129 | sourceTree = "";
130 | };
131 | 72BE8D5C1D3EC55E005720FB = {
132 | isa = PBXGroup;
133 | children = (
134 | 72BE8D681D3EC55E005720FB /* BoardingPass */,
135 | 72BE8D851D3FBCDE005720FB /* BoardingPassExample */,
136 | 72BE8D761D3FBC05005720FB /* BoardingPassTests */,
137 | 72BE8D671D3EC55E005720FB /* Products */,
138 | );
139 | sourceTree = "";
140 | };
141 | 72BE8D671D3EC55E005720FB /* Products */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 72BE8D661D3EC55E005720FB /* BoardingPass.framework */,
145 | 72BE8D751D3FBC05005720FB /* BoardingPassTests.xctest */,
146 | 72BE8D841D3FBCDE005720FB /* BoardingPassExample.app */,
147 | );
148 | name = Products;
149 | sourceTree = "";
150 | };
151 | 72BE8D681D3EC55E005720FB /* BoardingPass */ = {
152 | isa = PBXGroup;
153 | children = (
154 | 72BE8D981D3FBD0C005720FB /* Assets */,
155 | 7264CA2D1D3FEB2A00033FC4 /* BoardingInformation.swift */,
156 | 7264CA2B1D3FC69800033FC4 /* BoardingNavigationController.swift */,
157 | 7264CA341D4001BD00033FC4 /* HorizontalSlideAnimatedTransition.swift */,
158 | 23A09E261D908D05004A9ADF /* BoardingPassCompatibility.swift */,
159 | );
160 | path = BoardingPass;
161 | sourceTree = "";
162 | };
163 | 72BE8D761D3FBC05005720FB /* BoardingPassTests */ = {
164 | isa = PBXGroup;
165 | children = (
166 | 72BE8D971D3FBD00005720FB /* Assets */,
167 | 72BE8D771D3FBC05005720FB /* BoardingPassTests.swift */,
168 | );
169 | path = BoardingPassTests;
170 | sourceTree = "";
171 | };
172 | 72BE8D851D3FBCDE005720FB /* BoardingPassExample */ = {
173 | isa = PBXGroup;
174 | children = (
175 | 72BE8D991D3FBD26005720FB /* App Delegate */,
176 | 72BE8D961D3FBCEC005720FB /* Assets */,
177 | 72BE8D9A1D3FBD2F005720FB /* Onboarding Demo */,
178 | );
179 | path = BoardingPassExample;
180 | sourceTree = "";
181 | };
182 | 72BE8D961D3FBCEC005720FB /* Assets */ = {
183 | isa = PBXGroup;
184 | children = (
185 | 72BE8D8D1D3FBCDE005720FB /* Assets.xcassets */,
186 | 72BE8D921D3FBCDE005720FB /* Info.plist */,
187 | 72BE8D8F1D3FBCDE005720FB /* LaunchScreen.storyboard */,
188 | );
189 | path = Assets;
190 | sourceTree = "";
191 | };
192 | 72BE8D971D3FBD00005720FB /* Assets */ = {
193 | isa = PBXGroup;
194 | children = (
195 | 72BE8D791D3FBC05005720FB /* Info.plist */,
196 | );
197 | path = Assets;
198 | sourceTree = "";
199 | };
200 | 72BE8D981D3FBD0C005720FB /* Assets */ = {
201 | isa = PBXGroup;
202 | children = (
203 | 72BE8D691D3EC55E005720FB /* BoardingPass.h */,
204 | 72BE8D6B1D3EC55E005720FB /* Info.plist */,
205 | );
206 | path = Assets;
207 | sourceTree = "";
208 | };
209 | 72BE8D991D3FBD26005720FB /* App Delegate */ = {
210 | isa = PBXGroup;
211 | children = (
212 | 72BE8D861D3FBCDE005720FB /* AppDelegate.swift */,
213 | );
214 | path = "App Delegate";
215 | sourceTree = "";
216 | };
217 | 72BE8D9A1D3FBD2F005720FB /* Onboarding Demo */ = {
218 | isa = PBXGroup;
219 | children = (
220 | 7264CA311D3FEC4000033FC4 /* Completed View Controller */,
221 | 7264CA301D3FEC2A00033FC4 /* Process View Controllers */,
222 | 72BE8D881D3FBCDE005720FB /* OnboardingWrapperViewController.swift */,
223 | );
224 | path = "Onboarding Demo";
225 | sourceTree = "";
226 | };
227 | /* End PBXGroup section */
228 |
229 | /* Begin PBXHeadersBuildPhase section */
230 | 72BE8D631D3EC55E005720FB /* Headers */ = {
231 | isa = PBXHeadersBuildPhase;
232 | buildActionMask = 2147483647;
233 | files = (
234 | 72BE8D6A1D3EC55E005720FB /* BoardingPass.h in Headers */,
235 | );
236 | runOnlyForDeploymentPostprocessing = 0;
237 | };
238 | /* End PBXHeadersBuildPhase section */
239 |
240 | /* Begin PBXNativeTarget section */
241 | 72BE8D651D3EC55E005720FB /* BoardingPass */ = {
242 | isa = PBXNativeTarget;
243 | buildConfigurationList = 72BE8D6E1D3EC55E005720FB /* Build configuration list for PBXNativeTarget "BoardingPass" */;
244 | buildPhases = (
245 | 720EF3761DF9D136007A5E10 /* Swiftlint */,
246 | 72BE8D611D3EC55E005720FB /* Sources */,
247 | 72BE8D621D3EC55E005720FB /* Frameworks */,
248 | 72BE8D631D3EC55E005720FB /* Headers */,
249 | 72BE8D641D3EC55E005720FB /* Resources */,
250 | );
251 | buildRules = (
252 | );
253 | dependencies = (
254 | );
255 | name = BoardingPass;
256 | productName = BoardingPass;
257 | productReference = 72BE8D661D3EC55E005720FB /* BoardingPass.framework */;
258 | productType = "com.apple.product-type.framework";
259 | };
260 | 72BE8D741D3FBC05005720FB /* BoardingPassTests */ = {
261 | isa = PBXNativeTarget;
262 | buildConfigurationList = 72BE8D7F1D3FBC05005720FB /* Build configuration list for PBXNativeTarget "BoardingPassTests" */;
263 | buildPhases = (
264 | 72BE8D711D3FBC05005720FB /* Sources */,
265 | 72BE8D721D3FBC05005720FB /* Frameworks */,
266 | 72BE8D731D3FBC05005720FB /* Resources */,
267 | );
268 | buildRules = (
269 | );
270 | dependencies = (
271 | 72BE8D7C1D3FBC05005720FB /* PBXTargetDependency */,
272 | );
273 | name = BoardingPassTests;
274 | productName = BoardingPassTests;
275 | productReference = 72BE8D751D3FBC05005720FB /* BoardingPassTests.xctest */;
276 | productType = "com.apple.product-type.bundle.unit-test";
277 | };
278 | 72BE8D831D3FBCDE005720FB /* BoardingPassExample */ = {
279 | isa = PBXNativeTarget;
280 | buildConfigurationList = 72BE8D931D3FBCDE005720FB /* Build configuration list for PBXNativeTarget "BoardingPassExample" */;
281 | buildPhases = (
282 | 72BE8D801D3FBCDE005720FB /* Sources */,
283 | 72BE8D811D3FBCDE005720FB /* Frameworks */,
284 | 72BE8D821D3FBCDE005720FB /* Resources */,
285 | 7264CA2A1D3FC54A00033FC4 /* Embed Frameworks */,
286 | );
287 | buildRules = (
288 | );
289 | dependencies = (
290 | 7264CA291D3FC54A00033FC4 /* PBXTargetDependency */,
291 | );
292 | name = BoardingPassExample;
293 | productName = BoardingPassExample;
294 | productReference = 72BE8D841D3FBCDE005720FB /* BoardingPassExample.app */;
295 | productType = "com.apple.product-type.application";
296 | };
297 | /* End PBXNativeTarget section */
298 |
299 | /* Begin PBXProject section */
300 | 72BE8D5D1D3EC55E005720FB /* Project object */ = {
301 | isa = PBXProject;
302 | attributes = {
303 | LastSwiftUpdateCheck = 0730;
304 | LastUpgradeCheck = 0800;
305 | ORGANIZATIONNAME = Raizlabs;
306 | TargetAttributes = {
307 | 72BE8D651D3EC55E005720FB = {
308 | CreatedOnToolsVersion = 7.3.1;
309 | LastSwiftMigration = 0800;
310 | };
311 | 72BE8D741D3FBC05005720FB = {
312 | CreatedOnToolsVersion = 7.3.1;
313 | LastSwiftMigration = 0800;
314 | };
315 | 72BE8D831D3FBCDE005720FB = {
316 | CreatedOnToolsVersion = 7.3.1;
317 | LastSwiftMigration = 0800;
318 | };
319 | };
320 | };
321 | buildConfigurationList = 72BE8D601D3EC55E005720FB /* Build configuration list for PBXProject "BoardingPass" */;
322 | compatibilityVersion = "Xcode 3.2";
323 | developmentRegion = English;
324 | hasScannedForEncodings = 0;
325 | knownRegions = (
326 | en,
327 | Base,
328 | );
329 | mainGroup = 72BE8D5C1D3EC55E005720FB;
330 | productRefGroup = 72BE8D671D3EC55E005720FB /* Products */;
331 | projectDirPath = "";
332 | projectRoot = "";
333 | targets = (
334 | 72BE8D651D3EC55E005720FB /* BoardingPass */,
335 | 72BE8D741D3FBC05005720FB /* BoardingPassTests */,
336 | 72BE8D831D3FBCDE005720FB /* BoardingPassExample */,
337 | );
338 | };
339 | /* End PBXProject section */
340 |
341 | /* Begin PBXResourcesBuildPhase section */
342 | 72BE8D641D3EC55E005720FB /* Resources */ = {
343 | isa = PBXResourcesBuildPhase;
344 | buildActionMask = 2147483647;
345 | files = (
346 | );
347 | runOnlyForDeploymentPostprocessing = 0;
348 | };
349 | 72BE8D731D3FBC05005720FB /* Resources */ = {
350 | isa = PBXResourcesBuildPhase;
351 | buildActionMask = 2147483647;
352 | files = (
353 | );
354 | runOnlyForDeploymentPostprocessing = 0;
355 | };
356 | 72BE8D821D3FBCDE005720FB /* Resources */ = {
357 | isa = PBXResourcesBuildPhase;
358 | buildActionMask = 2147483647;
359 | files = (
360 | 72BE8D911D3FBCDE005720FB /* LaunchScreen.storyboard in Resources */,
361 | 72BE8D8E1D3FBCDE005720FB /* Assets.xcassets in Resources */,
362 | );
363 | runOnlyForDeploymentPostprocessing = 0;
364 | };
365 | /* End PBXResourcesBuildPhase section */
366 |
367 | /* Begin PBXShellScriptBuildPhase section */
368 | 720EF3761DF9D136007A5E10 /* Swiftlint */ = {
369 | isa = PBXShellScriptBuildPhase;
370 | buildActionMask = 2147483647;
371 | files = (
372 | );
373 | inputPaths = (
374 | );
375 | name = Swiftlint;
376 | outputPaths = (
377 | );
378 | runOnlyForDeploymentPostprocessing = 0;
379 | shellPath = /bin/sh;
380 | shellScript = "if which swiftlint >/dev/null; then\nswiftlint || echo \"warning: SwiftLint failed with exit code $?. Is SwiftLint installed and up to date?\"\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
381 | };
382 | /* End PBXShellScriptBuildPhase section */
383 |
384 | /* Begin PBXSourcesBuildPhase section */
385 | 72BE8D611D3EC55E005720FB /* Sources */ = {
386 | isa = PBXSourcesBuildPhase;
387 | buildActionMask = 2147483647;
388 | files = (
389 | 7264CA2E1D3FEB2A00033FC4 /* BoardingInformation.swift in Sources */,
390 | 23A09E271D908D05004A9ADF /* BoardingPassCompatibility.swift in Sources */,
391 | 7264CA351D4001BD00033FC4 /* HorizontalSlideAnimatedTransition.swift in Sources */,
392 | 7264CA2C1D3FC69800033FC4 /* BoardingNavigationController.swift in Sources */,
393 | );
394 | runOnlyForDeploymentPostprocessing = 0;
395 | };
396 | 72BE8D711D3FBC05005720FB /* Sources */ = {
397 | isa = PBXSourcesBuildPhase;
398 | buildActionMask = 2147483647;
399 | files = (
400 | 72BE8D781D3FBC05005720FB /* BoardingPassTests.swift in Sources */,
401 | );
402 | runOnlyForDeploymentPostprocessing = 0;
403 | };
404 | 72BE8D801D3FBCDE005720FB /* Sources */ = {
405 | isa = PBXSourcesBuildPhase;
406 | buildActionMask = 2147483647;
407 | files = (
408 | 72F163451D4910D1007D983B /* ActionableViewController.swift in Sources */,
409 | 7264CA331D3FEC4C00033FC4 /* CompletedViewController.swift in Sources */,
410 | 7264CA231D3FC4B300033FC4 /* SecondViewController.swift in Sources */,
411 | 7264CA211D3FC4AB00033FC4 /* FirstViewController.swift in Sources */,
412 | 7264CA251D3FC4B900033FC4 /* ThirdViewController.swift in Sources */,
413 | 72BE8D891D3FBCDE005720FB /* OnboardingWrapperViewController.swift in Sources */,
414 | 72BE8D871D3FBCDE005720FB /* AppDelegate.swift in Sources */,
415 | );
416 | runOnlyForDeploymentPostprocessing = 0;
417 | };
418 | /* End PBXSourcesBuildPhase section */
419 |
420 | /* Begin PBXTargetDependency section */
421 | 7264CA291D3FC54A00033FC4 /* PBXTargetDependency */ = {
422 | isa = PBXTargetDependency;
423 | target = 72BE8D651D3EC55E005720FB /* BoardingPass */;
424 | targetProxy = 7264CA281D3FC54A00033FC4 /* PBXContainerItemProxy */;
425 | };
426 | 72BE8D7C1D3FBC05005720FB /* PBXTargetDependency */ = {
427 | isa = PBXTargetDependency;
428 | target = 72BE8D651D3EC55E005720FB /* BoardingPass */;
429 | targetProxy = 72BE8D7B1D3FBC05005720FB /* PBXContainerItemProxy */;
430 | };
431 | /* End PBXTargetDependency section */
432 |
433 | /* Begin PBXVariantGroup section */
434 | 72BE8D8F1D3FBCDE005720FB /* LaunchScreen.storyboard */ = {
435 | isa = PBXVariantGroup;
436 | children = (
437 | 72BE8D901D3FBCDE005720FB /* Base */,
438 | );
439 | name = LaunchScreen.storyboard;
440 | path = .;
441 | sourceTree = "";
442 | };
443 | /* End PBXVariantGroup section */
444 |
445 | /* Begin XCBuildConfiguration section */
446 | 72BE8D6C1D3EC55E005720FB /* Debug */ = {
447 | isa = XCBuildConfiguration;
448 | buildSettings = {
449 | ALWAYS_SEARCH_USER_PATHS = NO;
450 | CLANG_ANALYZER_NONNULL = YES;
451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
452 | CLANG_CXX_LIBRARY = "libc++";
453 | CLANG_ENABLE_MODULES = YES;
454 | CLANG_ENABLE_OBJC_ARC = YES;
455 | CLANG_WARN_BOOL_CONVERSION = YES;
456 | CLANG_WARN_CONSTANT_CONVERSION = YES;
457 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
458 | CLANG_WARN_EMPTY_BODY = YES;
459 | CLANG_WARN_ENUM_CONVERSION = YES;
460 | CLANG_WARN_INFINITE_RECURSION = YES;
461 | CLANG_WARN_INT_CONVERSION = YES;
462 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
463 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
464 | CLANG_WARN_UNREACHABLE_CODE = YES;
465 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
466 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
467 | COPY_PHASE_STRIP = NO;
468 | CURRENT_PROJECT_VERSION = 1;
469 | DEBUG_INFORMATION_FORMAT = dwarf;
470 | ENABLE_STRICT_OBJC_MSGSEND = YES;
471 | ENABLE_TESTABILITY = YES;
472 | GCC_C_LANGUAGE_STANDARD = gnu99;
473 | GCC_DYNAMIC_NO_PIC = NO;
474 | GCC_NO_COMMON_BLOCKS = YES;
475 | GCC_OPTIMIZATION_LEVEL = 0;
476 | GCC_PREPROCESSOR_DEFINITIONS = (
477 | "DEBUG=1",
478 | "$(inherited)",
479 | );
480 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
481 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
482 | GCC_WARN_UNDECLARED_SELECTOR = YES;
483 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
484 | GCC_WARN_UNUSED_FUNCTION = YES;
485 | GCC_WARN_UNUSED_VARIABLE = YES;
486 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
487 | MTL_ENABLE_DEBUG_INFO = YES;
488 | ONLY_ACTIVE_ARCH = YES;
489 | SDKROOT = iphoneos;
490 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
491 | TARGETED_DEVICE_FAMILY = "1,2";
492 | VERSIONING_SYSTEM = "apple-generic";
493 | VERSION_INFO_PREFIX = "";
494 | };
495 | name = Debug;
496 | };
497 | 72BE8D6D1D3EC55E005720FB /* Release */ = {
498 | isa = XCBuildConfiguration;
499 | buildSettings = {
500 | ALWAYS_SEARCH_USER_PATHS = NO;
501 | CLANG_ANALYZER_NONNULL = YES;
502 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
503 | CLANG_CXX_LIBRARY = "libc++";
504 | CLANG_ENABLE_MODULES = YES;
505 | CLANG_ENABLE_OBJC_ARC = YES;
506 | CLANG_WARN_BOOL_CONVERSION = YES;
507 | CLANG_WARN_CONSTANT_CONVERSION = YES;
508 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
509 | CLANG_WARN_EMPTY_BODY = YES;
510 | CLANG_WARN_ENUM_CONVERSION = YES;
511 | CLANG_WARN_INFINITE_RECURSION = YES;
512 | CLANG_WARN_INT_CONVERSION = YES;
513 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
514 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
515 | CLANG_WARN_UNREACHABLE_CODE = YES;
516 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
517 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
518 | COPY_PHASE_STRIP = NO;
519 | CURRENT_PROJECT_VERSION = 1;
520 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
521 | ENABLE_NS_ASSERTIONS = NO;
522 | ENABLE_STRICT_OBJC_MSGSEND = YES;
523 | GCC_C_LANGUAGE_STANDARD = gnu99;
524 | GCC_NO_COMMON_BLOCKS = YES;
525 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
526 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
527 | GCC_WARN_UNDECLARED_SELECTOR = YES;
528 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
529 | GCC_WARN_UNUSED_FUNCTION = YES;
530 | GCC_WARN_UNUSED_VARIABLE = YES;
531 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
532 | MTL_ENABLE_DEBUG_INFO = NO;
533 | SDKROOT = iphoneos;
534 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
535 | TARGETED_DEVICE_FAMILY = "1,2";
536 | VALIDATE_PRODUCT = YES;
537 | VERSIONING_SYSTEM = "apple-generic";
538 | VERSION_INFO_PREFIX = "";
539 | };
540 | name = Release;
541 | };
542 | 72BE8D6F1D3EC55E005720FB /* Debug */ = {
543 | isa = XCBuildConfiguration;
544 | buildSettings = {
545 | CLANG_ENABLE_MODULES = YES;
546 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
547 | DEFINES_MODULE = YES;
548 | DYLIB_COMPATIBILITY_VERSION = 1;
549 | DYLIB_CURRENT_VERSION = 1;
550 | DYLIB_INSTALL_NAME_BASE = "@rpath";
551 | GCC_GENERATE_TEST_COVERAGE_FILES = NO;
552 | INFOPLIST_FILE = BoardingPass/Assets/Info.plist;
553 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
554 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
555 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
556 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPass;
557 | PRODUCT_NAME = "$(TARGET_NAME)";
558 | SKIP_INSTALL = YES;
559 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
560 | SWIFT_VERSION = 3.0;
561 | };
562 | name = Debug;
563 | };
564 | 72BE8D701D3EC55E005720FB /* Release */ = {
565 | isa = XCBuildConfiguration;
566 | buildSettings = {
567 | CLANG_ENABLE_MODULES = YES;
568 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
569 | DEFINES_MODULE = YES;
570 | DYLIB_COMPATIBILITY_VERSION = 1;
571 | DYLIB_CURRENT_VERSION = 1;
572 | DYLIB_INSTALL_NAME_BASE = "@rpath";
573 | GCC_GENERATE_TEST_COVERAGE_FILES = NO;
574 | INFOPLIST_FILE = BoardingPass/Assets/Info.plist;
575 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
576 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
578 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPass;
579 | PRODUCT_NAME = "$(TARGET_NAME)";
580 | SKIP_INSTALL = YES;
581 | SWIFT_VERSION = 3.0;
582 | };
583 | name = Release;
584 | };
585 | 72BE8D7D1D3FBC05005720FB /* Debug */ = {
586 | isa = XCBuildConfiguration;
587 | buildSettings = {
588 | INFOPLIST_FILE = BoardingPassTests/Assets/Info.plist;
589 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
590 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPassTests;
591 | PRODUCT_NAME = "$(TARGET_NAME)";
592 | SWIFT_VERSION = 3.0;
593 | };
594 | name = Debug;
595 | };
596 | 72BE8D7E1D3FBC05005720FB /* Release */ = {
597 | isa = XCBuildConfiguration;
598 | buildSettings = {
599 | INFOPLIST_FILE = BoardingPassTests/Assets/Info.plist;
600 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
601 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPassTests;
602 | PRODUCT_NAME = "$(TARGET_NAME)";
603 | SWIFT_VERSION = 3.0;
604 | };
605 | name = Release;
606 | };
607 | 72BE8D941D3FBCDE005720FB /* Debug */ = {
608 | isa = XCBuildConfiguration;
609 | buildSettings = {
610 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
611 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
612 | GCC_GENERATE_TEST_COVERAGE_FILES = NO;
613 | INFOPLIST_FILE = BoardingPassExample/Assets/Info.plist;
614 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
615 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
616 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPassExample;
617 | PRODUCT_NAME = "$(TARGET_NAME)";
618 | SWIFT_VERSION = 3.0;
619 | };
620 | name = Debug;
621 | };
622 | 72BE8D951D3FBCDE005720FB /* Release */ = {
623 | isa = XCBuildConfiguration;
624 | buildSettings = {
625 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
626 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
627 | GCC_GENERATE_TEST_COVERAGE_FILES = NO;
628 | INFOPLIST_FILE = BoardingPassExample/Assets/Info.plist;
629 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
630 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
631 | PRODUCT_BUNDLE_IDENTIFIER = com.raizlabs.BoardingPassExample;
632 | PRODUCT_NAME = "$(TARGET_NAME)";
633 | SWIFT_VERSION = 3.0;
634 | };
635 | name = Release;
636 | };
637 | /* End XCBuildConfiguration section */
638 |
639 | /* Begin XCConfigurationList section */
640 | 72BE8D601D3EC55E005720FB /* Build configuration list for PBXProject "BoardingPass" */ = {
641 | isa = XCConfigurationList;
642 | buildConfigurations = (
643 | 72BE8D6C1D3EC55E005720FB /* Debug */,
644 | 72BE8D6D1D3EC55E005720FB /* Release */,
645 | );
646 | defaultConfigurationIsVisible = 0;
647 | defaultConfigurationName = Release;
648 | };
649 | 72BE8D6E1D3EC55E005720FB /* Build configuration list for PBXNativeTarget "BoardingPass" */ = {
650 | isa = XCConfigurationList;
651 | buildConfigurations = (
652 | 72BE8D6F1D3EC55E005720FB /* Debug */,
653 | 72BE8D701D3EC55E005720FB /* Release */,
654 | );
655 | defaultConfigurationIsVisible = 0;
656 | defaultConfigurationName = Release;
657 | };
658 | 72BE8D7F1D3FBC05005720FB /* Build configuration list for PBXNativeTarget "BoardingPassTests" */ = {
659 | isa = XCConfigurationList;
660 | buildConfigurations = (
661 | 72BE8D7D1D3FBC05005720FB /* Debug */,
662 | 72BE8D7E1D3FBC05005720FB /* Release */,
663 | );
664 | defaultConfigurationIsVisible = 0;
665 | defaultConfigurationName = Release;
666 | };
667 | 72BE8D931D3FBCDE005720FB /* Build configuration list for PBXNativeTarget "BoardingPassExample" */ = {
668 | isa = XCConfigurationList;
669 | buildConfigurations = (
670 | 72BE8D941D3FBCDE005720FB /* Debug */,
671 | 72BE8D951D3FBCDE005720FB /* Release */,
672 | );
673 | defaultConfigurationIsVisible = 0;
674 | defaultConfigurationName = Release;
675 | };
676 | /* End XCConfigurationList section */
677 | };
678 | rootObject = 72BE8D5D1D3EC55E005720FB /* Project object */;
679 | }
680 |
--------------------------------------------------------------------------------