├── .swift-version ├── Assets ├── demo.gif ├── banner.png └── custom_examples.png ├── .gitignore ├── Example ├── OnboardExample │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── Onboarding1.imageset │ │ │ ├── Onboarding1.pdf │ │ │ └── Contents.json │ │ ├── Onboarding2.imageset │ │ │ ├── Onboarding2.pdf │ │ │ └── Contents.json │ │ ├── Onboarding3.imageset │ │ │ ├── Onboarding3.pdf │ │ │ └── Contents.json │ │ ├── Onboarding4.imageset │ │ │ ├── Onboarding4.pdf │ │ │ └── Contents.json │ │ ├── Onboarding5.imageset │ │ │ ├── Onboarding5.pdf │ │ │ └── Contents.json │ │ ├── Onboarding1_alt.imageset │ │ │ ├── app_logo_alt.pdf │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── ViewController.swift └── OnboardExample.xcodeproj │ └── project.pbxproj ├── OnboardKit.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── nikolakirev.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── xcshareddata │ └── xcschemes │ │ └── OnboardKit.xcscheme └── project.pbxproj ├── OnboardKit.xcworkspace ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── contents.xcworkspacedata ├── Package.swift ├── Metadata ├── OnboardKit.h └── Info.plist ├── OnboardKitTests ├── AppearanceConfigurationTests.swift └── Info.plist ├── OnboardKit.podspec ├── LICENSE ├── OnboardKit ├── OnboardPage.swift ├── OnboardPageViewController.swift └── OnboardViewController.swift └── README.md /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0 2 | -------------------------------------------------------------------------------- /Assets/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Assets/demo.gif -------------------------------------------------------------------------------- /Assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Assets/banner.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.xcbkptlist 2 | *.xcuserstate 3 | *.xcuserdata 4 | .DS_Store 5 | xcuserdata 6 | xcshareddata 7 | -------------------------------------------------------------------------------- /Assets/custom_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Assets/custom_examples.png -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding1.imageset/Onboarding1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding1.imageset/Onboarding1.pdf -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding2.imageset/Onboarding2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding2.imageset/Onboarding2.pdf -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding3.imageset/Onboarding3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding3.imageset/Onboarding3.pdf -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding4.imageset/Onboarding4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding4.imageset/Onboarding4.pdf -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding5.imageset/Onboarding5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding5.imageset/Onboarding5.pdf -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding1_alt.imageset/app_logo_alt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikolaKirev/OnboardKit/HEAD/Example/OnboardExample/Assets.xcassets/Onboarding1_alt.imageset/app_logo_alt.pdf -------------------------------------------------------------------------------- /OnboardKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Onboarding1.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Onboarding2.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Onboarding3.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Onboarding4.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Onboarding5.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/Onboarding1_alt.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "app_logo_alt.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /OnboardKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OnboardKit.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "OnboardKit", 6 | platforms: [.iOS(.v11)], 7 | products: [ 8 | .library(name: "OnboardKit", targets: ["OnboardKit"]) 9 | ], 10 | dependencies: [], 11 | targets: [ 12 | .target(name: "OnboardKit", path: "OnboardKit") 13 | ] 14 | ) -------------------------------------------------------------------------------- /Example/OnboardExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // OnboardExample 4 | // 5 | 6 | import UIKit 7 | 8 | @UIApplicationMain 9 | class AppDelegate: UIResponder, UIApplicationDelegate { 10 | 11 | var window: UIWindow? 12 | 13 | func application(_ application: UIApplication, 14 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 | return true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Metadata/OnboardKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardKit.h 3 | // OnboardKit 4 | // 5 | // Created by Nikola Kirev on 22/07/2017. 6 | // Copyright © 2017 Nikola Kirev. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for OnboardKit. 12 | FOUNDATION_EXPORT double OnboardKitVersionNumber; 13 | 14 | //! Project version string for OnboardKit. 15 | FOUNDATION_EXPORT const unsigned char OnboardKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /OnboardKitTests/AppearanceConfigurationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppearanceConfigurationTests.swift 3 | // OnboardKitTests 4 | // 5 | 6 | import XCTest 7 | @testable import OnboardKit 8 | 9 | final class AppearanceConfigurationTests: XCTestCase { 10 | 11 | func testAppearanceConfiguration_usesSpecificColor_whenTitleColorSpecified() { 12 | let sut = OnboardViewController.AppearanceConfiguration(titleColor: .purple, textColor: .green) 13 | XCTAssertNotEqual(sut.titleColor, .green) 14 | XCTAssertEqual(sut.titleColor, .purple) 15 | } 16 | 17 | func testAppearanceConfiguration_usesTextColor_whenTitleColorNotSpecified() { 18 | let sut = OnboardViewController.AppearanceConfiguration(textColor: .green) 19 | XCTAssertEqual(sut.titleColor, .green) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /OnboardKitTests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /OnboardKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "OnboardKit" 4 | s.version = "1.5.0" 5 | s.summary = "Customisable user onboarding for your iOS app" 6 | 7 | s.description = <<-DESC 8 | OnboardKit gives you an easy way to add onboarding to your iOS app. 9 | It is written in Swift. 10 | DESC 11 | 12 | s.homepage = "https://github.com/NikolaKirev/OnboardKit" 13 | 14 | s.license = { :type => "MIT", :file => "LICENSE" } 15 | 16 | s.author = { "Nikola Kirev" => "n@nikolakirev.com" } 17 | s.social_media_url = "http://twitter.com/NikolaKirev" 18 | 19 | s.platform = :ios, "11.0" 20 | 21 | s.source = { :git => "https://github.com/NikolaKirev/OnboardKit.git", :tag => "v1.5.0" } 22 | s.source_files = "OnboardKit" 23 | 24 | end 25 | -------------------------------------------------------------------------------- /Metadata/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 | 1.4.2 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /OnboardKit.xcodeproj/xcuserdata/nikolakirev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | OnboardKit.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9437E2A41F238E7E00E294BE 16 | 17 | primary 18 | 19 | 20 | 9437E2AD1F238E7E00E294BE 21 | 22 | primary 23 | 24 | 25 | 9437E2D11F2392FC00E294BE 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Nikola Kirev 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 | -------------------------------------------------------------------------------- /Example/OnboardExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.3.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 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 | -------------------------------------------------------------------------------- /Example/OnboardExample/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 | -------------------------------------------------------------------------------- /OnboardKit/OnboardPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardPage.swift 3 | // OnboardKit 4 | // 5 | 6 | import Foundation 7 | 8 | public typealias OnboardPageCompletion = ((_ success: Bool, _ error: Error?) -> Void) 9 | public typealias OnboardPageAction = (@escaping OnboardPageCompletion) -> Void 10 | 11 | public struct OnboardPage { 12 | /// The title text used for the top label of the onboarding page 13 | let title: String 14 | 15 | /// An optional image to be used in the onboarding page 16 | /// 17 | /// - note: If no image is used, the description label will adjust fill the empty space 18 | let imageName: String? 19 | 20 | /// An optional description text to be used underneath the image 21 | /// 22 | /// - note: If no description text is used, the image will adjust fill the empty space 23 | let description: String? 24 | 25 | /// The title text to be used for the secondary button that is used to advance to the next page 26 | let advanceButtonTitle: String 27 | 28 | /// The title text to be used for the optional action button on the page 29 | /// 30 | /// - note: If no action button title is set, the button will not appear 31 | let actionButtonTitle: String? 32 | 33 | /// The action to be called when tapping the action button on the page 34 | /// 35 | /// - note: calling the completion on the action will advance the onboarding to the next page 36 | let action: OnboardPageAction? 37 | 38 | public init(title: String, 39 | imageName: String? = nil, 40 | description: String?, 41 | advanceButtonTitle: String = NSLocalizedString("Next", comment: ""), 42 | actionButtonTitle: String? = nil, 43 | action: OnboardPageAction? = nil) { 44 | self.title = title 45 | self.imageName = imageName 46 | self.description = description 47 | self.advanceButtonTitle = advanceButtonTitle 48 | self.actionButtonTitle = actionButtonTitle 49 | self.action = action 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/OnboardExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /OnboardKit.xcodeproj/xcshareddata/xcschemes/OnboardKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![OnboardKit](Assets/banner.png) 2 | 3 | [![Swift 5.0](https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat)](https://developer.apple.com/swift/) 4 | [![Version](https://img.shields.io/cocoapods/v/OnboardKit.svg?style=flat)](http://cocoapods.org/pods/OnboardKit) 5 | [![License](https://img.shields.io/cocoapods/l/OnboardKit.svg?style=flat)](http://cocoapods.org/pods/OnboardKit) 6 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 7 | [![Twitter](https://img.shields.io/badge/twitter-@NikolaKirev-blue.svg?style=flat)](https://twitter.com/NikolaKirev) 8 | 9 | # OnboardKit 10 | *Customizable user onboarding for your UIKit app in Swift* 11 | 12 |

13 | 14 | ## Requirements 15 | 16 | * Swift 5.0 17 | * Xcode 10 18 | * iOS 11.0+ 19 | 20 | ## Installation 21 | 22 | #### [Carthage](https://github.com/Carthage/Carthage) 23 | 24 | ````bash 25 | github "NikolaKirev/OnboardKit" 26 | ```` 27 | 28 | #### [CocoaPods](http://cocoapods.org) 29 | 30 | ````ruby 31 | use_frameworks! 32 | 33 | # Latest release in CocoaPods 34 | pod 'OnboardKit' 35 | 36 | # Get the latest on master 37 | pod 'OnboardKit', :git => 'https://github.com/NikolaKirev/OnboardKit.git', :branch => 'master' 38 | ```` 39 | 40 | Don't forget to `import OnboardKit` in the file you intend to use it. 41 | 42 | ## Usage 43 | 44 | 1. Create and populate a bunch of `OnboardPage` instances 45 | ````swift 46 | let page = OnboardPage(title: "Welcome to OnboardKit", 47 | imageName: "Onboarding1", 48 | description: "OnboardKit helps you add onboarding to your iOS app") 49 | ```` 50 | 2. Create an `OnboardViewController` 51 | ````swift 52 | let onboardingViewController = OnboardViewController(pageItems: [pageOne, ...]) 53 | ```` 54 | 3. Present the view controller 55 | ````swift 56 | onboardingViewController.presentFrom(self, animated: true) 57 | ```` 58 | (use this convenience method to make sure you present it modally) 59 | 60 | ## Customization 61 | 62 | ![Custom examples](Assets/custom_examples.png) 63 | 64 | #### Customizing Fonts and Colors 65 | You can customize the look of your onboarding by changing the default colors and fonts. 66 | 67 | 1. Initialize an `AppearanceConfiguration` instance with the desired custom style properties 68 | ````swift 69 | let appearance = AppearanceConfiguration(tintColor: .orange, 70 | titleColor: .red, 71 | textColor: .white, 72 | backgroundColor: .black, 73 | imageContentMode: .scaleAspectFit, 74 | titleFont: UIFont.boldSystemFont(ofSize: 32.0), 75 | textFont: UIFont.boldSystemFont(ofSize: 17.0)) 76 | ```` 77 | 2. Pass the `AppearanceConfiguration` instance as a parameter when initialising an `OnboardViewController` 78 | ````swift 79 | let onboardingVC = OnboardViewController(pageItems: onboardingPages, 80 | appearanceConfiguration: appearance) 81 | ```` 82 | 83 | ##### List of customizable properties: 84 | - `tintColor` - used for tinting the advance and action buttons 85 | - `titleColor` - used to set title color (textColor is used if not specified) 86 | - `textColor` - used to set description text color 87 | - `backgroundColor` - used to set view background color 88 | - `imageContentMode` - used to set the content mode of page imageViews 89 | - `titleFont` - used to set the title font (used for the action button font as well) 90 | - `textFont` - used to set the description text font (used for the advance button font as well) 91 | - `advanceButtonStyling` - a block used to customize the advance button 92 | - `actionButtonStyling` - a block used to customize the action button 93 | 94 | #### Customizing Buttons 95 | To customize the style of the advance and action buttons on each page of the onboarding flow, you can use a `ButtonStyling` closure. 96 | 97 | 1. Create the closure 98 | ````swift 99 | let advanceButtonStyling: OnboardViewController.ButtonStyling = { button in 100 | button.setTitleColor(UIColor.lightGray, for: .normal) 101 | button.titleLabel?.font = UIFont.systemFont(ofSize: 16.0, weight: .semibold) 102 | } 103 | ```` 104 | 2. Pass the closure in the `AppearanceConfiguration` initializer 105 | ````swift 106 | let appearance = OnboardViewController.AppearanceConfiguration(tintColor: .orange, 107 | advanceButtonStyling: advanceButtonStyling) 108 | ```` 109 | 110 | ## Author 111 | 112 | ### Nikola Kirev 113 | 114 | * Website: [http://nikolakirev.com](http://nikolakirev.com) 115 | * Twitter: [@NikolaKirev](http://twitter.com/nikolakirev) 116 | 117 | ## License 118 | 119 | OnboardKit is available under the MIT license. See the [LICENSE](https://github.com/NikolaKirev/OnboardKit/blob/master/LICENSE) file for more info. 120 | -------------------------------------------------------------------------------- /Example/OnboardExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Example/OnboardExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // OnboardExample 4 | // 5 | 6 | import UIKit 7 | import OnboardKit 8 | 9 | class ViewController: UIViewController { 10 | 11 | lazy var onboardingPages: [OnboardPage] = { 12 | let pageOne = OnboardPage(title: "Welcome to Habitat", 13 | imageName: "Onboarding1", 14 | description: "Habitat is an easy to use productivity app designed to keep you motivated.") 15 | 16 | let pageTwo = OnboardPage(title: "Habit Entries", 17 | imageName: "Onboarding2", 18 | description: "For each of your habits an entry is created for every day you need to complete it.") 19 | 20 | let pageThree = OnboardPage(title: "Marking and Tracking", 21 | imageName: "Onboarding3", 22 | description: "By marking entries as Done you can track your progress on the path to success.") 23 | 24 | let pageFour = OnboardPage(title: "Notifications", 25 | imageName: "Onboarding4", 26 | description: "Turn on notifications to get reminders and keep up with your goals.", 27 | advanceButtonTitle: "Decide Later", 28 | actionButtonTitle: "Enable Notifications", 29 | action: { [weak self] completion in 30 | self?.showAlert(completion) 31 | }) 32 | 33 | let pageFive = OnboardPage(title: "All Ready", 34 | imageName: "Onboarding5", 35 | description: "You are all set up and ready to use Habitat. Begin by adding your first habit.", 36 | advanceButtonTitle: "Done") 37 | 38 | return [pageOne, pageTwo, pageThree, pageFour, pageFive] 39 | }() 40 | 41 | lazy var onboardingPagesAlternative: [OnboardPage] = { 42 | let pageOne = OnboardPage(title: "Welcome to Habitat", 43 | imageName: "Onboarding1_alt", 44 | description: "Habitat is an easy to use productivity app designed to keep you motivated.") 45 | 46 | let pageTwo = OnboardPage(title: "Habit Entries", 47 | imageName: "Onboarding2", 48 | description: "An entry is created for every day you need to complete each habit.") 49 | 50 | let pageThree = OnboardPage(title: "Marking and Tracking", 51 | imageName: "Onboarding3", 52 | description: "By marking entries as Done you can track your progress.") 53 | 54 | let pageFour = OnboardPage(title: "Notifications", 55 | imageName: "Onboarding4", 56 | description: "Turn on notifications to get reminders and keep up with your goals.", 57 | advanceButtonTitle: "Decide Later", 58 | actionButtonTitle: "Enable Notifications", 59 | action: { [weak self] completion in 60 | self?.showAlert(completion) 61 | }) 62 | 63 | let pageFive = OnboardPage(title: "All Ready", 64 | imageName: "Onboarding5", 65 | description: "You are all set up and ready to use Habitat. Adding your first habit.", 66 | advanceButtonTitle: "Done") 67 | 68 | return [pageOne, pageTwo, pageThree, pageFour, pageFive] 69 | }() 70 | 71 | @IBAction func showOnboardingDefaultTapped(_ sender: Any) { 72 | let onboardingVC = OnboardViewController(pageItems: onboardingPages, completion: { 73 | print("onboarding complete") 74 | }) 75 | onboardingVC.modalPresentationStyle = .formSheet 76 | onboardingVC.presentFrom(self, animated: true) 77 | } 78 | 79 | @IBAction func showOnboardingCustomTapped(_ sender: Any) { 80 | let tintColor = UIColor(red: 1.00, green: 0.52, blue: 0.40, alpha: 1.00) 81 | let titleColor = UIColor(red: 1.00, green: 0.35, blue: 0.43, alpha: 1.00) 82 | let boldTitleFont = UIFont.systemFont(ofSize: 32.0, weight: .bold) 83 | let mediumTextFont = UIFont.systemFont(ofSize: 17.0, weight: .semibold) 84 | let appearanceConfiguration = OnboardViewController.AppearanceConfiguration(tintColor: tintColor, 85 | titleColor: titleColor, 86 | textColor: .white, 87 | backgroundColor: .black, 88 | titleFont: boldTitleFont, 89 | textFont: mediumTextFont) 90 | let onboardingVC = OnboardViewController(pageItems: onboardingPagesAlternative, 91 | appearanceConfiguration: appearanceConfiguration) 92 | onboardingVC.modalPresentationStyle = .formSheet 93 | onboardingVC.presentFrom(self, animated: true) 94 | } 95 | 96 | @IBAction func showOnboardingStyledButtonsTapped(_ sender: Any) { 97 | let advanceButtonStyling: OnboardViewController.ButtonStyling = { button in 98 | button.setTitleColor(UIColor.lightGray, for: .normal) 99 | button.titleLabel?.font = UIFont.systemFont(ofSize: 16.0, weight: .semibold) 100 | } 101 | let actionButtonStyling: OnboardViewController.ButtonStyling = { button in 102 | button.setTitleColor(.black, for: .normal) 103 | button.titleLabel?.font = UIFont.systemFont(ofSize: 22.0, weight: .semibold) 104 | button.backgroundColor = UIColor(white: 0.95, alpha: 1.0) 105 | button.layer.cornerRadius = button.bounds.height / 2.0 106 | button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) 107 | button.layer.shadowColor = UIColor.black.cgColor 108 | button.layer.shadowOffset = CGSize(width: 0.0, height: 1.0) 109 | button.layer.shadowRadius = 2.0 110 | button.layer.shadowOpacity = 0.2 111 | } 112 | let appearance = OnboardViewController.AppearanceConfiguration(advanceButtonStyling: advanceButtonStyling, 113 | actionButtonStyling: actionButtonStyling) 114 | let onboardingVC = OnboardViewController(pageItems: onboardingPages, 115 | appearanceConfiguration: appearance) 116 | onboardingVC.modalPresentationStyle = .formSheet 117 | onboardingVC.presentFrom(self, animated: true) 118 | } 119 | 120 | /// Only for the purpouses of the example. 121 | /// Not really asking for notifications permissions. 122 | private func showAlert(_ completion: @escaping (_ success: Bool, _ error: Error?) -> Void) { 123 | let alert = UIAlertController(title: "Allow Notifications?", 124 | message: "Habitat wants to send you notifications", 125 | preferredStyle: .alert) 126 | alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in 127 | completion(true, nil) 128 | }) 129 | alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in 130 | completion(false, nil) 131 | }) 132 | presentedViewController?.present(alert, animated: true) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /OnboardKit/OnboardPageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardPageViewController.swift 3 | // OnboardKit 4 | // 5 | 6 | import UIKit 7 | 8 | internal protocol OnboardPageViewControllerDelegate: class { 9 | 10 | /// Informs the `delegate` that the action button was tapped 11 | /// 12 | /// - Parameters: 13 | /// - pageVC: The `OnboardPageViewController` object 14 | /// - index: The page index 15 | func pageViewController(_ pageVC: OnboardPageViewController, actionTappedAt index: Int) 16 | 17 | /// Informs the `delegate` that the advance(next) button was tapped 18 | /// 19 | /// - Parameters: 20 | /// - pageVC: The `OnboardPageViewController` object 21 | /// - index: The page index 22 | func pageViewController(_ pageVC: OnboardPageViewController, advanceTappedAt index: Int) 23 | } 24 | 25 | internal final class OnboardPageViewController: UIViewController { 26 | 27 | private lazy var pageStackView: UIStackView = { 28 | let stackView = UIStackView() 29 | stackView.translatesAutoresizingMaskIntoConstraints = false 30 | stackView.spacing = 16.0 31 | stackView.axis = .vertical 32 | stackView.alignment = .center 33 | return stackView 34 | }() 35 | 36 | private lazy var titleLabel: UILabel = { 37 | let label = UILabel() 38 | label.translatesAutoresizingMaskIntoConstraints = false 39 | label.font = UIFont.preferredFont(forTextStyle: .title1) 40 | label.numberOfLines = 0 41 | label.textAlignment = .center 42 | return label 43 | }() 44 | 45 | private lazy var imageView: UIImageView = { 46 | let imageView = UIImageView() 47 | imageView.translatesAutoresizingMaskIntoConstraints = false 48 | return imageView 49 | }() 50 | 51 | private lazy var descriptionLabel: UILabel = { 52 | let label = UILabel() 53 | label.translatesAutoresizingMaskIntoConstraints = false 54 | label.font = UIFont.preferredFont(forTextStyle: .title3) 55 | label.numberOfLines = 0 56 | label.textAlignment = .center 57 | return label 58 | }() 59 | 60 | private lazy var actionButton: UIButton = { 61 | let button = UIButton() 62 | button.translatesAutoresizingMaskIntoConstraints = false 63 | button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title2) 64 | return button 65 | }() 66 | 67 | private lazy var advanceButton: UIButton = { 68 | let button = UIButton() 69 | button.translatesAutoresizingMaskIntoConstraints = false 70 | button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body) 71 | return button 72 | }() 73 | 74 | let pageIndex: Int 75 | 76 | weak var delegate: OnboardPageViewControllerDelegate? 77 | 78 | private let appearanceConfiguration: OnboardViewController.AppearanceConfiguration 79 | 80 | init(pageIndex: Int, appearanceConfiguration: OnboardViewController.AppearanceConfiguration) { 81 | self.pageIndex = pageIndex 82 | self.appearanceConfiguration = appearanceConfiguration 83 | super.init(nibName: nil, bundle: nil) 84 | customizeStyleWith(appearanceConfiguration) 85 | } 86 | 87 | required init?(coder aDecoder: NSCoder) { 88 | fatalError("init(coder:) has not been implemented") 89 | } 90 | 91 | private func customizeStyleWith(_ appearanceConfiguration: OnboardViewController.AppearanceConfiguration) { 92 | view.backgroundColor = appearanceConfiguration.backgroundColor 93 | // Setup imageView 94 | imageView.contentMode = appearanceConfiguration.imageContentMode 95 | // Style title 96 | titleLabel.textColor = appearanceConfiguration.titleColor 97 | titleLabel.font = appearanceConfiguration.titleFont 98 | // Style description 99 | descriptionLabel.textColor = appearanceConfiguration.textColor 100 | descriptionLabel.font = appearanceConfiguration.textFont 101 | } 102 | 103 | private func customizeButtonsWith(_ appearanceConfiguration: OnboardViewController.AppearanceConfiguration) { 104 | advanceButton.sizeToFit() 105 | if let advanceButtonStyling = appearanceConfiguration.advanceButtonStyling { 106 | advanceButtonStyling(advanceButton) 107 | } else { 108 | advanceButton.setTitleColor(appearanceConfiguration.tintColor, for: .normal) 109 | advanceButton.titleLabel?.font = appearanceConfiguration.textFont 110 | } 111 | actionButton.sizeToFit() 112 | if let actionButtonStyling = appearanceConfiguration.actionButtonStyling { 113 | actionButtonStyling(actionButton) 114 | } else { 115 | actionButton.setTitleColor(appearanceConfiguration.tintColor, for: .normal) 116 | actionButton.titleLabel?.font = appearanceConfiguration.titleFont 117 | } 118 | } 119 | 120 | override func loadView() { 121 | view = UIView(frame: CGRect.zero) 122 | view.addSubview(titleLabel) 123 | view.addSubview(pageStackView) 124 | NSLayoutConstraint.activate([ 125 | titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), 126 | titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16.0), 127 | pageStackView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16.0), 128 | pageStackView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor), 129 | pageStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), 130 | pageStackView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor) 131 | ]) 132 | pageStackView.addArrangedSubview(imageView) 133 | pageStackView.addArrangedSubview(descriptionLabel) 134 | pageStackView.addArrangedSubview(actionButton) 135 | pageStackView.addArrangedSubview(advanceButton) 136 | 137 | actionButton.addTarget(self, 138 | action: #selector(OnboardPageViewController.actionTapped), 139 | for: .touchUpInside) 140 | advanceButton.addTarget(self, 141 | action: #selector(OnboardPageViewController.advanceTapped), 142 | for: .touchUpInside) 143 | 144 | } 145 | 146 | override func viewWillAppear(_ animated: Bool) { 147 | super.viewWillAppear(animated) 148 | customizeButtonsWith(appearanceConfiguration) 149 | } 150 | 151 | func configureWithPage(_ page: OnboardPage) { 152 | configureTitleLabel(page.title) 153 | configureImageView(page.imageName) 154 | configureDescriptionLabel(page.description) 155 | configureActionButton(page.actionButtonTitle, action: page.action) 156 | configureAdvanceButton(page.advanceButtonTitle) 157 | } 158 | 159 | private func configureTitleLabel(_ title: String) { 160 | titleLabel.text = title 161 | NSLayoutConstraint.activate([ 162 | titleLabel.widthAnchor.constraint(equalTo: pageStackView.widthAnchor, multiplier: 0.8) 163 | ]) 164 | } 165 | 166 | private func configureImageView(_ imageName: String?) { 167 | if let imageName = imageName, let image = UIImage(named: imageName) { 168 | imageView.image = image 169 | imageView.heightAnchor.constraint(equalTo: pageStackView.heightAnchor, multiplier: 0.5).isActive = true 170 | } else { 171 | imageView.isHidden = true 172 | } 173 | } 174 | 175 | private func configureDescriptionLabel(_ description: String?) { 176 | if let pageDescription = description { 177 | descriptionLabel.text = pageDescription 178 | NSLayoutConstraint.activate([ 179 | descriptionLabel.heightAnchor.constraint(greaterThanOrEqualTo: pageStackView.heightAnchor, multiplier: 0.2), 180 | descriptionLabel.widthAnchor.constraint(equalTo: pageStackView.widthAnchor, multiplier: 0.8) 181 | ]) 182 | } else { 183 | descriptionLabel.isHidden = true 184 | } 185 | } 186 | 187 | private func configureActionButton(_ title: String?, action: OnboardPageAction?) { 188 | if let actionButtonTitle = title { 189 | actionButton.setTitle(actionButtonTitle, for: .normal) 190 | } else { 191 | actionButton.isHidden = true 192 | } 193 | } 194 | 195 | private func configureAdvanceButton(_ title: String) { 196 | advanceButton.setTitle(title, for: .normal) 197 | } 198 | 199 | // MARK: - User Actions 200 | @objc fileprivate func actionTapped() { 201 | delegate?.pageViewController(self, actionTappedAt: pageIndex) 202 | } 203 | 204 | @objc fileprivate func advanceTapped() { 205 | delegate?.pageViewController(self, advanceTappedAt: pageIndex) 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /OnboardKit/OnboardViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardViewController.swift 3 | // OnboardKit 4 | // 5 | 6 | import UIKit 7 | 8 | /** 9 | */ 10 | final public class OnboardViewController: UIViewController { 11 | 12 | private let pageViewController = UIPageViewController(transitionStyle: .scroll, 13 | navigationOrientation: .horizontal, 14 | options: nil) 15 | private let pageItems: [OnboardPage] 16 | private let appearanceConfiguration: AppearanceConfiguration 17 | private let completion: (() -> Void)? 18 | 19 | required public init?(coder: NSCoder) { 20 | fatalError("init(coder:) has not been implemented") 21 | } 22 | 23 | /// Initializes a new `OnboardViewController` to be presented 24 | /// The onboard view controller encapsulates the whole onboarding flow 25 | /// 26 | /// - Parameters: 27 | /// - pageItems: An array of `OnboardPage` items 28 | /// - appearanceConfiguration: An optional configuration struct for appearance customization 29 | /// - completion: An optional completion block that gets executed when the onboarding VC is dismissed 30 | public init(pageItems: [OnboardPage], 31 | appearanceConfiguration: AppearanceConfiguration = AppearanceConfiguration(), 32 | completion: (() -> Void)? = nil) { 33 | self.pageItems = pageItems 34 | self.appearanceConfiguration = appearanceConfiguration 35 | self.completion = completion 36 | super.init(nibName: nil, bundle: nil) 37 | } 38 | 39 | override public var supportedInterfaceOrientations: UIInterfaceOrientationMask { 40 | return .portrait 41 | } 42 | 43 | override public func loadView() { 44 | view = UIView(frame: CGRect.zero) 45 | view.backgroundColor = appearanceConfiguration.backgroundColor 46 | pageViewController.setViewControllers([pageViwControllerFor(pageIndex: 0)!], 47 | direction: .forward, 48 | animated: false, 49 | completion: nil) 50 | pageViewController.dataSource = self 51 | pageViewController.delegate = self 52 | pageViewController.view.frame = view.bounds 53 | 54 | let pageControlApperance = UIPageControl.appearance(whenContainedInInstancesOf: [OnboardViewController.self]) 55 | pageControlApperance.pageIndicatorTintColor = appearanceConfiguration.tintColor.withAlphaComponent(0.3) 56 | pageControlApperance.currentPageIndicatorTintColor = appearanceConfiguration.tintColor 57 | 58 | addChild(pageViewController) 59 | view.addSubview(pageViewController.view) 60 | pageViewController.didMove(toParent: self) 61 | } 62 | 63 | private func pageViwControllerFor(pageIndex: Int) -> OnboardPageViewController? { 64 | let pageVC = OnboardPageViewController(pageIndex: pageIndex, appearanceConfiguration: appearanceConfiguration) 65 | guard pageIndex >= 0 else { return nil } 66 | guard pageIndex < pageItems.count else { return nil } 67 | pageVC.delegate = self 68 | pageVC.configureWithPage(pageItems[pageIndex]) 69 | return pageVC 70 | } 71 | 72 | private func advanceToPageWithIndex(_ pageIndex: Int) { 73 | DispatchQueue.main.async { [weak self] in 74 | guard let nextPage = self?.pageViwControllerFor(pageIndex: pageIndex) else { return } 75 | self?.pageViewController.setViewControllers([nextPage], 76 | direction: .forward, 77 | animated: true, 78 | completion: nil) 79 | } 80 | } 81 | } 82 | 83 | // MARK: Presenting 84 | public extension OnboardViewController { 85 | 86 | /// Presents the configured `OnboardViewController` 87 | /// 88 | /// - Parameters: 89 | /// - viewController: the presenting view controller 90 | /// - animated: Defines if the presentation should be animated 91 | func presentFrom(_ viewController: UIViewController, animated: Bool) { 92 | viewController.present(self, animated: animated) 93 | } 94 | } 95 | 96 | extension OnboardViewController: UIPageViewControllerDataSource { 97 | 98 | public func pageViewController(_ pageViewController: UIPageViewController, 99 | viewControllerBefore viewController: UIViewController) -> UIViewController? { 100 | guard let pageVC = viewController as? OnboardPageViewController else { return nil } 101 | let pageIndex = pageVC.pageIndex 102 | guard pageIndex != 0 else { return nil } 103 | return pageViwControllerFor(pageIndex: pageIndex - 1) 104 | } 105 | 106 | public func pageViewController(_ pageViewController: UIPageViewController, 107 | viewControllerAfter viewController: UIViewController) -> UIViewController? { 108 | guard let pageVC = viewController as? OnboardPageViewController else { return nil } 109 | let pageIndex = pageVC.pageIndex 110 | return pageViwControllerFor(pageIndex: pageIndex + 1) 111 | } 112 | 113 | public func presentationCount(for pageViewController: UIPageViewController) -> Int { 114 | return pageItems.count 115 | } 116 | 117 | public func presentationIndex(for pageViewController: UIPageViewController) -> Int { 118 | if let currentPage = pageViewController.viewControllers?.first as? OnboardPageViewController { 119 | return currentPage.pageIndex 120 | } 121 | return 0 122 | } 123 | } 124 | 125 | extension OnboardViewController: UIPageViewControllerDelegate { 126 | 127 | } 128 | 129 | extension OnboardViewController: OnboardPageViewControllerDelegate { 130 | 131 | func pageViewController(_ pageVC: OnboardPageViewController, actionTappedAt index: Int) { 132 | if let pageAction = pageItems[index].action { 133 | pageAction({ (success, error) in 134 | guard error == nil else { return } 135 | if success { 136 | self.advanceToPageWithIndex(index + 1) 137 | } 138 | }) 139 | } 140 | } 141 | 142 | func pageViewController(_ pageVC: OnboardPageViewController, advanceTappedAt index: Int) { 143 | if index == pageItems.count - 1 { 144 | dismiss(animated: true, completion: self.completion) 145 | } else { 146 | advanceToPageWithIndex(index + 1) 147 | } 148 | } 149 | } 150 | 151 | // MARK: - AppearanceConfiguration 152 | public extension OnboardViewController { 153 | 154 | typealias ButtonStyling = ((UIButton) -> Void) 155 | 156 | struct AppearanceConfiguration { 157 | /// The color used for the page indicator and buttons 158 | /// 159 | /// - note: Defualts to the blue tint color used troughout iOS 160 | let tintColor: UIColor 161 | 162 | /// The color used for the title text 163 | /// 164 | /// - note: If not specified, defualts to whatever `textColor` is 165 | let titleColor: UIColor 166 | 167 | /// The color used for the description text (and title text `titleColor` if not set) 168 | /// 169 | /// - note: Defualts to `.darkText` 170 | let textColor: UIColor 171 | 172 | /// The color used for onboarding background 173 | /// 174 | /// - note: Defualts to white 175 | let backgroundColor: UIColor 176 | 177 | /// The `contentMode` used for the slide imageView 178 | /// 179 | /// - note: Defualts to white 180 | let imageContentMode: UIView.ContentMode 181 | 182 | /// The font used for the title and action button 183 | /// 184 | /// - note: Defualts to preferred text style `.title1` (supports dinamyc type) 185 | let titleFont: UIFont 186 | 187 | /// The font used for the desctiption label and advance button 188 | /// 189 | /// - note: Defualts to preferred text style `.body` (supports dinamyc type) 190 | let textFont: UIFont 191 | 192 | /// A Swift closure used to expose and customize the button used to advance to the next page 193 | /// 194 | /// - note: Defualts to nil. If not used, the button will be customized based on the tint and text properties 195 | let advanceButtonStyling: ButtonStyling? 196 | 197 | /// A Swift closure used to expose and customize the button used to trigger page specific action 198 | /// 199 | /// - note: Defualts to nil. If not used, the button will be customized based on the title properties 200 | let actionButtonStyling: ButtonStyling? 201 | 202 | public init(tintColor: UIColor = UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0), 203 | titleColor: UIColor? = nil, 204 | textColor: UIColor = .darkText, 205 | backgroundColor: UIColor = .white, 206 | imageContentMode: UIView.ContentMode = .center, 207 | titleFont: UIFont = UIFont.preferredFont(forTextStyle: .title1), 208 | textFont: UIFont = UIFont.preferredFont(forTextStyle: .body), 209 | advanceButtonStyling: ButtonStyling? = nil, 210 | actionButtonStyling: ButtonStyling? = nil) { 211 | self.tintColor = tintColor 212 | self.titleColor = titleColor ?? textColor 213 | self.textColor = textColor 214 | self.backgroundColor = backgroundColor 215 | self.imageContentMode = imageContentMode 216 | self.titleFont = titleFont 217 | self.textFont = textFont 218 | self.advanceButtonStyling = advanceButtonStyling 219 | self.actionButtonStyling = actionButtonStyling 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Example/OnboardExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9497BC2820D701F800CCC791 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9497BC2720D701F800CCC791 /* AppDelegate.swift */; }; 11 | 9497BC2A20D701F800CCC791 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9497BC2920D701F800CCC791 /* ViewController.swift */; }; 12 | 9497BC2D20D701F800CCC791 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9497BC2B20D701F800CCC791 /* Main.storyboard */; }; 13 | 9497BC2F20D701F900CCC791 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9497BC2E20D701F900CCC791 /* Assets.xcassets */; }; 14 | 9497BC3220D701F900CCC791 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9497BC3020D701F900CCC791 /* LaunchScreen.storyboard */; }; 15 | 9497BC4120D7029D00CCC791 /* OnboardKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9497BC4020D7029D00CCC791 /* OnboardKit.framework */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 9497BC2420D701F800CCC791 /* OnboardExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OnboardExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 9497BC2720D701F800CCC791 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 9497BC2920D701F800CCC791 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 22 | 9497BC2C20D701F800CCC791 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 23 | 9497BC2E20D701F900CCC791 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | 9497BC3120D701F900CCC791 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 25 | 9497BC3320D701F900CCC791 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 9497BC4020D7029D00CCC791 /* OnboardKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OnboardKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 9497BC2120D701F800CCC791 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | 9497BC4120D7029D00CCC791 /* OnboardKit.framework in Frameworks */, 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 9497BC1B20D701F800CCC791 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 9497BC2620D701F800CCC791 /* OnboardExample */, 45 | 9497BC2520D701F800CCC791 /* Products */, 46 | 9497BC3F20D7029D00CCC791 /* Frameworks */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | 9497BC2520D701F800CCC791 /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 9497BC2420D701F800CCC791 /* OnboardExample.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | 9497BC2620D701F800CCC791 /* OnboardExample */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 9497BC2720D701F800CCC791 /* AppDelegate.swift */, 62 | 9497BC2920D701F800CCC791 /* ViewController.swift */, 63 | 9497BC2B20D701F800CCC791 /* Main.storyboard */, 64 | 9497BC2E20D701F900CCC791 /* Assets.xcassets */, 65 | 9497BC3020D701F900CCC791 /* LaunchScreen.storyboard */, 66 | 9497BC3320D701F900CCC791 /* Info.plist */, 67 | ); 68 | path = OnboardExample; 69 | sourceTree = ""; 70 | }; 71 | 9497BC3F20D7029D00CCC791 /* Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 9497BC4020D7029D00CCC791 /* OnboardKit.framework */, 75 | ); 76 | name = Frameworks; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 9497BC2320D701F800CCC791 /* OnboardExample */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 9497BC3620D701F900CCC791 /* Build configuration list for PBXNativeTarget "OnboardExample" */; 85 | buildPhases = ( 86 | 9497BC2020D701F800CCC791 /* Sources */, 87 | 9497BC2120D701F800CCC791 /* Frameworks */, 88 | 9497BC2220D701F800CCC791 /* Resources */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = OnboardExample; 95 | productName = OnboardExample; 96 | productReference = 9497BC2420D701F800CCC791 /* OnboardExample.app */; 97 | productType = "com.apple.product-type.application"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | 9497BC1C20D701F800CCC791 /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastSwiftUpdateCheck = 0940; 106 | LastUpgradeCheck = 0940; 107 | TargetAttributes = { 108 | 9497BC2320D701F800CCC791 = { 109 | CreatedOnToolsVersion = 9.4; 110 | LastSwiftMigration = 1020; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 9497BC1F20D701F800CCC791 /* Build configuration list for PBXProject "OnboardExample" */; 115 | compatibilityVersion = "Xcode 9.3"; 116 | developmentRegion = en; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 9497BC1B20D701F800CCC791; 123 | productRefGroup = 9497BC2520D701F800CCC791 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 9497BC2320D701F800CCC791 /* OnboardExample */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXResourcesBuildPhase section */ 133 | 9497BC2220D701F800CCC791 /* Resources */ = { 134 | isa = PBXResourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 9497BC3220D701F900CCC791 /* LaunchScreen.storyboard in Resources */, 138 | 9497BC2F20D701F900CCC791 /* Assets.xcassets in Resources */, 139 | 9497BC2D20D701F800CCC791 /* Main.storyboard in Resources */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXResourcesBuildPhase section */ 144 | 145 | /* Begin PBXSourcesBuildPhase section */ 146 | 9497BC2020D701F800CCC791 /* Sources */ = { 147 | isa = PBXSourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 9497BC2A20D701F800CCC791 /* ViewController.swift in Sources */, 151 | 9497BC2820D701F800CCC791 /* AppDelegate.swift in Sources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXSourcesBuildPhase section */ 156 | 157 | /* Begin PBXVariantGroup section */ 158 | 9497BC2B20D701F800CCC791 /* Main.storyboard */ = { 159 | isa = PBXVariantGroup; 160 | children = ( 161 | 9497BC2C20D701F800CCC791 /* Base */, 162 | ); 163 | name = Main.storyboard; 164 | sourceTree = ""; 165 | }; 166 | 9497BC3020D701F900CCC791 /* LaunchScreen.storyboard */ = { 167 | isa = PBXVariantGroup; 168 | children = ( 169 | 9497BC3120D701F900CCC791 /* Base */, 170 | ); 171 | name = LaunchScreen.storyboard; 172 | sourceTree = ""; 173 | }; 174 | /* End PBXVariantGroup section */ 175 | 176 | /* Begin XCBuildConfiguration section */ 177 | 9497BC3420D701F900CCC791 /* Debug */ = { 178 | isa = XCBuildConfiguration; 179 | buildSettings = { 180 | ALWAYS_SEARCH_USER_PATHS = NO; 181 | CLANG_ANALYZER_NONNULL = YES; 182 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 183 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 184 | CLANG_CXX_LIBRARY = "libc++"; 185 | CLANG_ENABLE_MODULES = YES; 186 | CLANG_ENABLE_OBJC_ARC = YES; 187 | CLANG_ENABLE_OBJC_WEAK = YES; 188 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 189 | CLANG_WARN_BOOL_CONVERSION = YES; 190 | CLANG_WARN_COMMA = YES; 191 | CLANG_WARN_CONSTANT_CONVERSION = YES; 192 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 194 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 195 | CLANG_WARN_EMPTY_BODY = YES; 196 | CLANG_WARN_ENUM_CONVERSION = YES; 197 | CLANG_WARN_INFINITE_RECURSION = YES; 198 | CLANG_WARN_INT_CONVERSION = YES; 199 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 200 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 201 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 202 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 203 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 204 | CLANG_WARN_STRICT_PROTOTYPES = YES; 205 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 206 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 207 | CLANG_WARN_UNREACHABLE_CODE = YES; 208 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 209 | CODE_SIGN_IDENTITY = "iPhone Developer"; 210 | COPY_PHASE_STRIP = NO; 211 | DEBUG_INFORMATION_FORMAT = dwarf; 212 | ENABLE_STRICT_OBJC_MSGSEND = YES; 213 | ENABLE_TESTABILITY = YES; 214 | GCC_C_LANGUAGE_STANDARD = gnu11; 215 | GCC_DYNAMIC_NO_PIC = NO; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_OPTIMIZATION_LEVEL = 0; 218 | GCC_PREPROCESSOR_DEFINITIONS = ( 219 | "DEBUG=1", 220 | "$(inherited)", 221 | ); 222 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 223 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 224 | GCC_WARN_UNDECLARED_SELECTOR = YES; 225 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 226 | GCC_WARN_UNUSED_FUNCTION = YES; 227 | GCC_WARN_UNUSED_VARIABLE = YES; 228 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 229 | MTL_ENABLE_DEBUG_INFO = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = iphoneos; 232 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 233 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 234 | }; 235 | name = Debug; 236 | }; 237 | 9497BC3520D701F900CCC791 /* Release */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | CLANG_ANALYZER_NONNULL = YES; 242 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 243 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 244 | CLANG_CXX_LIBRARY = "libc++"; 245 | CLANG_ENABLE_MODULES = YES; 246 | CLANG_ENABLE_OBJC_ARC = YES; 247 | CLANG_ENABLE_OBJC_WEAK = YES; 248 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_COMMA = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 253 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 254 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 255 | CLANG_WARN_EMPTY_BODY = YES; 256 | CLANG_WARN_ENUM_CONVERSION = YES; 257 | CLANG_WARN_INFINITE_RECURSION = YES; 258 | CLANG_WARN_INT_CONVERSION = YES; 259 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 261 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 262 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 263 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 264 | CLANG_WARN_STRICT_PROTOTYPES = YES; 265 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 266 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 267 | CLANG_WARN_UNREACHABLE_CODE = YES; 268 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 269 | CODE_SIGN_IDENTITY = "iPhone Developer"; 270 | COPY_PHASE_STRIP = NO; 271 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 272 | ENABLE_NS_ASSERTIONS = NO; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu11; 275 | GCC_NO_COMMON_BLOCKS = YES; 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 278 | GCC_WARN_UNDECLARED_SELECTOR = YES; 279 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 280 | GCC_WARN_UNUSED_FUNCTION = YES; 281 | GCC_WARN_UNUSED_VARIABLE = YES; 282 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 283 | MTL_ENABLE_DEBUG_INFO = NO; 284 | SDKROOT = iphoneos; 285 | SWIFT_COMPILATION_MODE = wholemodule; 286 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 287 | VALIDATE_PRODUCT = YES; 288 | }; 289 | name = Release; 290 | }; 291 | 9497BC3720D701F900CCC791 /* Debug */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | CODE_SIGN_STYLE = Manual; 296 | DEVELOPMENT_TEAM = ""; 297 | INFOPLIST_FILE = OnboardExample/Info.plist; 298 | LD_RUNPATH_SEARCH_PATHS = ( 299 | "$(inherited)", 300 | "@executable_path/Frameworks", 301 | ); 302 | PRODUCT_BUNDLE_IDENTIFIER = com.onboardkit.OnboardExample; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | PROVISIONING_PROFILE_SPECIFIER = ""; 305 | SWIFT_VERSION = 5.0; 306 | TARGETED_DEVICE_FAMILY = "1,2"; 307 | }; 308 | name = Debug; 309 | }; 310 | 9497BC3820D701F900CCC791 /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 314 | CODE_SIGN_STYLE = Manual; 315 | DEVELOPMENT_TEAM = ""; 316 | INFOPLIST_FILE = OnboardExample/Info.plist; 317 | LD_RUNPATH_SEARCH_PATHS = ( 318 | "$(inherited)", 319 | "@executable_path/Frameworks", 320 | ); 321 | PRODUCT_BUNDLE_IDENTIFIER = com.onboardkit.OnboardExample; 322 | PRODUCT_NAME = "$(TARGET_NAME)"; 323 | PROVISIONING_PROFILE_SPECIFIER = ""; 324 | SWIFT_VERSION = 5.0; 325 | TARGETED_DEVICE_FAMILY = "1,2"; 326 | }; 327 | name = Release; 328 | }; 329 | /* End XCBuildConfiguration section */ 330 | 331 | /* Begin XCConfigurationList section */ 332 | 9497BC1F20D701F800CCC791 /* Build configuration list for PBXProject "OnboardExample" */ = { 333 | isa = XCConfigurationList; 334 | buildConfigurations = ( 335 | 9497BC3420D701F900CCC791 /* Debug */, 336 | 9497BC3520D701F900CCC791 /* Release */, 337 | ); 338 | defaultConfigurationIsVisible = 0; 339 | defaultConfigurationName = Release; 340 | }; 341 | 9497BC3620D701F900CCC791 /* Build configuration list for PBXNativeTarget "OnboardExample" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | 9497BC3720D701F900CCC791 /* Debug */, 345 | 9497BC3820D701F900CCC791 /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | defaultConfigurationName = Release; 349 | }; 350 | /* End XCConfigurationList section */ 351 | }; 352 | rootObject = 9497BC1C20D701F800CCC791 /* Project object */; 353 | } 354 | -------------------------------------------------------------------------------- /OnboardKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9437E2AF1F238E7E00E294BE /* OnboardKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9437E2A51F238E7E00E294BE /* OnboardKit.framework */; }; 11 | 9437E2C91F23920800E294BE /* OnboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437E2C41F23920800E294BE /* OnboardViewController.swift */; }; 12 | 9437E2CB1F23920800E294BE /* OnboardPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437E2C61F23920800E294BE /* OnboardPageViewController.swift */; }; 13 | 9437E2CC1F23920800E294BE /* OnboardPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437E2C71F23920800E294BE /* OnboardPage.swift */; }; 14 | 9449158B1F23D4D300191E79 /* OnboardKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9449158A1F23D4D300191E79 /* OnboardKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | 94FF39BE217B237C005AA773 /* AppearanceConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94FF39BD217B237C005AA773 /* AppearanceConfigurationTests.swift */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 9437E2B01F238E7E00E294BE /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 9437E29C1F238E7E00E294BE /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 9437E2A41F238E7E00E294BE; 24 | remoteInfo = OnboardKit; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 9416058D22843B270028102B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 30 | 9437E2A51F238E7E00E294BE /* OnboardKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OnboardKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 9437E2AE1F238E7E00E294BE /* OnboardKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OnboardKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 9437E2B51F238E7E00E294BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 9437E2C11F2391F700E294BE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 9437E2C41F23920800E294BE /* OnboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardViewController.swift; sourceTree = ""; }; 35 | 9437E2C61F23920800E294BE /* OnboardPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardPageViewController.swift; sourceTree = ""; }; 36 | 9437E2C71F23920800E294BE /* OnboardPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardPage.swift; sourceTree = ""; }; 37 | 9449158A1F23D4D300191E79 /* OnboardKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnboardKit.h; sourceTree = ""; }; 38 | 94FF39BD217B237C005AA773 /* AppearanceConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceConfigurationTests.swift; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 9437E2A11F238E7E00E294BE /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | 9437E2AB1F238E7E00E294BE /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 9437E2AF1F238E7E00E294BE /* OnboardKit.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 9437E29B1F238E7E00E294BE = { 61 | isa = PBXGroup; 62 | children = ( 63 | 9416058D22843B270028102B /* README.md */, 64 | 9437E2A71F238E7E00E294BE /* OnboardKit */, 65 | 9437E2BF1F23913600E294BE /* Metadata */, 66 | 9437E2B21F238E7E00E294BE /* OnboardKitTests */, 67 | 9437E2A61F238E7E00E294BE /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | 9437E2A61F238E7E00E294BE /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 9437E2A51F238E7E00E294BE /* OnboardKit.framework */, 75 | 9437E2AE1F238E7E00E294BE /* OnboardKitTests.xctest */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 9437E2A71F238E7E00E294BE /* OnboardKit */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 9437E2C41F23920800E294BE /* OnboardViewController.swift */, 84 | 9437E2C61F23920800E294BE /* OnboardPageViewController.swift */, 85 | 9437E2C71F23920800E294BE /* OnboardPage.swift */, 86 | ); 87 | path = OnboardKit; 88 | sourceTree = ""; 89 | }; 90 | 9437E2B21F238E7E00E294BE /* OnboardKitTests */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 94FF39BD217B237C005AA773 /* AppearanceConfigurationTests.swift */, 94 | 9437E2B51F238E7E00E294BE /* Info.plist */, 95 | ); 96 | path = OnboardKitTests; 97 | sourceTree = ""; 98 | }; 99 | 9437E2BF1F23913600E294BE /* Metadata */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 9449158A1F23D4D300191E79 /* OnboardKit.h */, 103 | 9437E2C11F2391F700E294BE /* Info.plist */, 104 | ); 105 | path = Metadata; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXHeadersBuildPhase section */ 111 | 9437E2A21F238E7E00E294BE /* Headers */ = { 112 | isa = PBXHeadersBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 9449158B1F23D4D300191E79 /* OnboardKit.h in Headers */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXHeadersBuildPhase section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | 9437E2A41F238E7E00E294BE /* OnboardKit */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = 9437E2B91F238E7E00E294BE /* Build configuration list for PBXNativeTarget "OnboardKit" */; 125 | buildPhases = ( 126 | 9437E2A01F238E7E00E294BE /* Sources */, 127 | 9437E2A11F238E7E00E294BE /* Frameworks */, 128 | 9437E2A21F238E7E00E294BE /* Headers */, 129 | 9437E2A31F238E7E00E294BE /* Resources */, 130 | 94938724201F1F2400EF9415 /* Swift Lint */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = OnboardKit; 137 | productName = OnboardKit; 138 | productReference = 9437E2A51F238E7E00E294BE /* OnboardKit.framework */; 139 | productType = "com.apple.product-type.framework"; 140 | }; 141 | 9437E2AD1F238E7E00E294BE /* OnboardKitTests */ = { 142 | isa = PBXNativeTarget; 143 | buildConfigurationList = 9437E2BC1F238E7E00E294BE /* Build configuration list for PBXNativeTarget "OnboardKitTests" */; 144 | buildPhases = ( 145 | 9437E2AA1F238E7E00E294BE /* Sources */, 146 | 9437E2AB1F238E7E00E294BE /* Frameworks */, 147 | 9437E2AC1F238E7E00E294BE /* Resources */, 148 | ); 149 | buildRules = ( 150 | ); 151 | dependencies = ( 152 | 9437E2B11F238E7E00E294BE /* PBXTargetDependency */, 153 | ); 154 | name = OnboardKitTests; 155 | productName = OnboardKitTests; 156 | productReference = 9437E2AE1F238E7E00E294BE /* OnboardKitTests.xctest */; 157 | productType = "com.apple.product-type.bundle.unit-test"; 158 | }; 159 | /* End PBXNativeTarget section */ 160 | 161 | /* Begin PBXProject section */ 162 | 9437E29C1F238E7E00E294BE /* Project object */ = { 163 | isa = PBXProject; 164 | attributes = { 165 | LastSwiftUpdateCheck = 0830; 166 | LastUpgradeCheck = 1020; 167 | ORGANIZATIONNAME = "Nikola Kirev"; 168 | TargetAttributes = { 169 | 9437E2A41F238E7E00E294BE = { 170 | CreatedOnToolsVersion = 8.3.3; 171 | LastSwiftMigration = 1020; 172 | ProvisioningStyle = Manual; 173 | }; 174 | 9437E2AD1F238E7E00E294BE = { 175 | CreatedOnToolsVersion = 8.3.3; 176 | DevelopmentTeam = 5Z8M29P3V9; 177 | LastSwiftMigration = 1020; 178 | ProvisioningStyle = Manual; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 9437E29F1F238E7E00E294BE /* Build configuration list for PBXProject "OnboardKit" */; 183 | compatibilityVersion = "Xcode 3.2"; 184 | developmentRegion = en; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | Base, 189 | ); 190 | mainGroup = 9437E29B1F238E7E00E294BE; 191 | productRefGroup = 9437E2A61F238E7E00E294BE /* Products */; 192 | projectDirPath = ""; 193 | projectRoot = ""; 194 | targets = ( 195 | 9437E2A41F238E7E00E294BE /* OnboardKit */, 196 | 9437E2AD1F238E7E00E294BE /* OnboardKitTests */, 197 | ); 198 | }; 199 | /* End PBXProject section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 9437E2A31F238E7E00E294BE /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | 9437E2AC1F238E7E00E294BE /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXResourcesBuildPhase section */ 217 | 218 | /* Begin PBXShellScriptBuildPhase section */ 219 | 94938724201F1F2400EF9415 /* Swift Lint */ = { 220 | isa = PBXShellScriptBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ); 224 | inputPaths = ( 225 | ); 226 | name = "Swift Lint"; 227 | outputPaths = ( 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | shellPath = /bin/sh; 231 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; 232 | }; 233 | /* End PBXShellScriptBuildPhase section */ 234 | 235 | /* Begin PBXSourcesBuildPhase section */ 236 | 9437E2A01F238E7E00E294BE /* Sources */ = { 237 | isa = PBXSourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | 9437E2CC1F23920800E294BE /* OnboardPage.swift in Sources */, 241 | 9437E2CB1F23920800E294BE /* OnboardPageViewController.swift in Sources */, 242 | 9437E2C91F23920800E294BE /* OnboardViewController.swift in Sources */, 243 | ); 244 | runOnlyForDeploymentPostprocessing = 0; 245 | }; 246 | 9437E2AA1F238E7E00E294BE /* Sources */ = { 247 | isa = PBXSourcesBuildPhase; 248 | buildActionMask = 2147483647; 249 | files = ( 250 | 94FF39BE217B237C005AA773 /* AppearanceConfigurationTests.swift in Sources */, 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | /* End PBXSourcesBuildPhase section */ 255 | 256 | /* Begin PBXTargetDependency section */ 257 | 9437E2B11F238E7E00E294BE /* PBXTargetDependency */ = { 258 | isa = PBXTargetDependency; 259 | target = 9437E2A41F238E7E00E294BE /* OnboardKit */; 260 | targetProxy = 9437E2B01F238E7E00E294BE /* PBXContainerItemProxy */; 261 | }; 262 | /* End PBXTargetDependency section */ 263 | 264 | /* Begin XCBuildConfiguration section */ 265 | 9437E2B71F238E7E00E294BE /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 270 | CLANG_ANALYZER_NONNULL = YES; 271 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 277 | CLANG_WARN_BOOL_CONVERSION = YES; 278 | CLANG_WARN_COMMA = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 281 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 282 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 283 | CLANG_WARN_EMPTY_BODY = YES; 284 | CLANG_WARN_ENUM_CONVERSION = YES; 285 | CLANG_WARN_INFINITE_RECURSION = YES; 286 | CLANG_WARN_INT_CONVERSION = YES; 287 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 288 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 289 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 291 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 292 | CLANG_WARN_STRICT_PROTOTYPES = YES; 293 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 294 | CLANG_WARN_UNREACHABLE_CODE = YES; 295 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 296 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 297 | COPY_PHASE_STRIP = NO; 298 | CURRENT_PROJECT_VERSION = 1; 299 | DEBUG_INFORMATION_FORMAT = dwarf; 300 | ENABLE_STRICT_OBJC_MSGSEND = YES; 301 | ENABLE_TESTABILITY = YES; 302 | GCC_C_LANGUAGE_STANDARD = gnu99; 303 | GCC_DYNAMIC_NO_PIC = NO; 304 | GCC_NO_COMMON_BLOCKS = YES; 305 | GCC_OPTIMIZATION_LEVEL = 0; 306 | GCC_PREPROCESSOR_DEFINITIONS = ( 307 | "DEBUG=1", 308 | "$(inherited)", 309 | ); 310 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 311 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 312 | GCC_WARN_UNDECLARED_SELECTOR = YES; 313 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 314 | GCC_WARN_UNUSED_FUNCTION = YES; 315 | GCC_WARN_UNUSED_VARIABLE = YES; 316 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 317 | MTL_ENABLE_DEBUG_INFO = YES; 318 | ONLY_ACTIVE_ARCH = YES; 319 | SDKROOT = iphoneos; 320 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 321 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 322 | TARGETED_DEVICE_FAMILY = "1,2"; 323 | VERSIONING_SYSTEM = "apple-generic"; 324 | VERSION_INFO_PREFIX = ""; 325 | }; 326 | name = Debug; 327 | }; 328 | 9437E2B81F238E7E00E294BE /* Release */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ALWAYS_SEARCH_USER_PATHS = NO; 332 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 333 | CLANG_ANALYZER_NONNULL = YES; 334 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 344 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 345 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 346 | CLANG_WARN_EMPTY_BODY = YES; 347 | CLANG_WARN_ENUM_CONVERSION = YES; 348 | CLANG_WARN_INFINITE_RECURSION = YES; 349 | CLANG_WARN_INT_CONVERSION = YES; 350 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 351 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 352 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 354 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 355 | CLANG_WARN_STRICT_PROTOTYPES = YES; 356 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 360 | COPY_PHASE_STRIP = NO; 361 | CURRENT_PROJECT_VERSION = 1; 362 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 363 | ENABLE_NS_ASSERTIONS = NO; 364 | ENABLE_STRICT_OBJC_MSGSEND = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_NO_COMMON_BLOCKS = YES; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 374 | MTL_ENABLE_DEBUG_INFO = NO; 375 | SDKROOT = iphoneos; 376 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 377 | TARGETED_DEVICE_FAMILY = "1,2"; 378 | VALIDATE_PRODUCT = YES; 379 | VERSIONING_SYSTEM = "apple-generic"; 380 | VERSION_INFO_PREFIX = ""; 381 | }; 382 | name = Release; 383 | }; 384 | 9437E2BA1F238E7E00E294BE /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | CLANG_ENABLE_MODULES = YES; 388 | CODE_SIGN_IDENTITY = ""; 389 | CODE_SIGN_STYLE = Manual; 390 | DEFINES_MODULE = YES; 391 | DEVELOPMENT_TEAM = ""; 392 | DYLIB_COMPATIBILITY_VERSION = 1; 393 | DYLIB_CURRENT_VERSION = 1; 394 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 395 | INFOPLIST_FILE = "$(SRCROOT)/Metadata/Info.plist"; 396 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 397 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 398 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 399 | PRODUCT_BUNDLE_IDENTIFIER = com.nikolakirev.OnboardKit; 400 | PRODUCT_NAME = "$(TARGET_NAME)"; 401 | PROVISIONING_PROFILE_SPECIFIER = ""; 402 | SKIP_INSTALL = YES; 403 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 404 | SWIFT_VERSION = 5.0; 405 | }; 406 | name = Debug; 407 | }; 408 | 9437E2BB1F238E7E00E294BE /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | CLANG_ENABLE_MODULES = YES; 412 | CODE_SIGN_IDENTITY = ""; 413 | CODE_SIGN_STYLE = Manual; 414 | DEFINES_MODULE = YES; 415 | DEVELOPMENT_TEAM = ""; 416 | DYLIB_COMPATIBILITY_VERSION = 1; 417 | DYLIB_CURRENT_VERSION = 1; 418 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 419 | INFOPLIST_FILE = "$(SRCROOT)/Metadata/Info.plist"; 420 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 421 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 422 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 423 | PRODUCT_BUNDLE_IDENTIFIER = com.nikolakirev.OnboardKit; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | PROVISIONING_PROFILE_SPECIFIER = ""; 426 | SKIP_INSTALL = YES; 427 | SWIFT_VERSION = 5.0; 428 | }; 429 | name = Release; 430 | }; 431 | 9437E2BD1F238E7E00E294BE /* Debug */ = { 432 | isa = XCBuildConfiguration; 433 | buildSettings = { 434 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 435 | CODE_SIGN_STYLE = Manual; 436 | DEVELOPMENT_TEAM = 5Z8M29P3V9; 437 | INFOPLIST_FILE = OnboardKitTests/Info.plist; 438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 439 | PRODUCT_BUNDLE_IDENTIFIER = com.nikolakirev.OnboardKitTests; 440 | PRODUCT_NAME = "$(TARGET_NAME)"; 441 | PROVISIONING_PROFILE_SPECIFIER = ""; 442 | SWIFT_VERSION = 5.0; 443 | }; 444 | name = Debug; 445 | }; 446 | 9437E2BE1F238E7E00E294BE /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 450 | CODE_SIGN_STYLE = Manual; 451 | DEVELOPMENT_TEAM = 5Z8M29P3V9; 452 | INFOPLIST_FILE = OnboardKitTests/Info.plist; 453 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 454 | PRODUCT_BUNDLE_IDENTIFIER = com.nikolakirev.OnboardKitTests; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | PROVISIONING_PROFILE_SPECIFIER = ""; 457 | SWIFT_VERSION = 5.0; 458 | }; 459 | name = Release; 460 | }; 461 | /* End XCBuildConfiguration section */ 462 | 463 | /* Begin XCConfigurationList section */ 464 | 9437E29F1F238E7E00E294BE /* Build configuration list for PBXProject "OnboardKit" */ = { 465 | isa = XCConfigurationList; 466 | buildConfigurations = ( 467 | 9437E2B71F238E7E00E294BE /* Debug */, 468 | 9437E2B81F238E7E00E294BE /* Release */, 469 | ); 470 | defaultConfigurationIsVisible = 0; 471 | defaultConfigurationName = Release; 472 | }; 473 | 9437E2B91F238E7E00E294BE /* Build configuration list for PBXNativeTarget "OnboardKit" */ = { 474 | isa = XCConfigurationList; 475 | buildConfigurations = ( 476 | 9437E2BA1F238E7E00E294BE /* Debug */, 477 | 9437E2BB1F238E7E00E294BE /* Release */, 478 | ); 479 | defaultConfigurationIsVisible = 0; 480 | defaultConfigurationName = Release; 481 | }; 482 | 9437E2BC1F238E7E00E294BE /* Build configuration list for PBXNativeTarget "OnboardKitTests" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | 9437E2BD1F238E7E00E294BE /* Debug */, 486 | 9437E2BE1F238E7E00E294BE /* Release */, 487 | ); 488 | defaultConfigurationIsVisible = 0; 489 | defaultConfigurationName = Release; 490 | }; 491 | /* End XCConfigurationList section */ 492 | }; 493 | rootObject = 9437E29C1F238E7E00E294BE /* Project object */; 494 | } 495 | --------------------------------------------------------------------------------