9 |
10 | //! Project version number for TiltedTabView.
11 | FOUNDATION_EXPORT double TiltedTabViewVersionNumber;
12 |
13 | //! Project version string for TiltedTabView.
14 | FOUNDATION_EXPORT const unsigned char TiltedTabViewVersionString[];
15 |
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ian McDowell
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tilted Tab View
2 |
3 |
4 | TiltedTabView •
5 | TabView •
6 | InputAssistant •
7 | Git
8 |
9 |
10 | --------
11 |
12 | This library aims to replicate the tab switcher in Safari on iOS. It handles both compact width (tilted) and regular width (grid) layouts.
13 |
14 | [](https://travis-ci.org/IMcD23/TiltedTabView)
15 | [](https://github.com/IMcD23/TiltedTabView/releases/latest)
16 | 
17 | [](https://twitter.com/ian_mcdowell)
18 |
19 |
20 |
21 | # Requirements
22 |
23 | * Xcode 9 or later
24 | * iOS 10.0 or later
25 |
26 | # Usage
27 |
28 | The main class in this library is the TiltedTabViewController. It is a subclass of UICollectionViewController, that contains a custom collection view and layout.
29 |
30 | To get started, create a view controller that subclasses TiltedTabViewController
31 |
32 | The TiltedTabViewController has data source and delegate properties, similar to those of a UICollectionView.
33 |
34 | Set an object that conforms to the TiltedTabViewControllerDataSource and TiltedTabViewControllerDelegate protocols as the dataSource and delegate properties, respectively.
35 |
36 | Provide implementations for all required methods of each protocol, and you're off to the races.
37 |
38 | # Installation
39 |
40 | ## Carthage
41 | To install TiltedTabView using [Carthage](https://github.com/Carthage/Carthage), add the following line to your Cartfile:
42 |
43 | ```
44 | github "IMcD23/TiltedTabView" "master"
45 | ```
46 |
47 | ## Submodule
48 | To install TiltedTabView as a submodule into your git repository, run the following command:
49 |
50 | ```
51 | git submodule add -b master https://github.com/IMcD23/TiltedTabView.git Path/To/TiltedTabView
52 | git submodule update --init --recursive
53 | ```
54 |
55 | Then, add the `.xcodeproj` in the root of the repository into your Xcode project, and add it as a build dependency.
56 |
57 | ## ibuild
58 | A Swift static library of this project is also available for the ibuild build system. Learn more about ibuild [here](https://github.com/IMcD23/ibuild)
59 |
60 | # Author
61 | Created by [Ian McDowell](https://ianmcdowell.net)
62 |
63 | # License
64 | All code in this project is available under the license specified in the LICENSE file. However, since this project also bundles code from other projects, you are subject to those projects' licenses as well.
65 |
--------------------------------------------------------------------------------
/Resources/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ian-mcdowell/TiltedTabView/30c11397991c5b7a9ab54eb5d372cbcb27e38126/Resources/Screenshot.png
--------------------------------------------------------------------------------
/Resources/Screenshot_iPad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ian-mcdowell/TiltedTabView/30c11397991c5b7a9ab54eb5d372cbcb27e38126/Resources/Screenshot_iPad.png
--------------------------------------------------------------------------------
/Sample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @UIApplicationMain
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 |
6 | var window: UIWindow?
7 |
8 |
9 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
10 |
11 | self.window = UIWindow(frame: UIScreen.main.bounds)
12 | self.window?.tintColor = .white
13 | self.window?.rootViewController = UINavigationController(rootViewController: ViewController())
14 | self.window?.makeKeyAndVisible()
15 |
16 | return true
17 | }
18 |
19 | func applicationWillResignActive(_ application: UIApplication) {
20 | }
21 |
22 | func applicationDidEnterBackground(_ application: UIApplication) {
23 | }
24 |
25 | func applicationWillEnterForeground(_ application: UIApplication) {
26 | }
27 |
28 | func applicationDidBecomeActive(_ application: UIApplication) {
29 | }
30 |
31 | func applicationWillTerminate(_ application: UIApplication) {
32 | }
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/Sample/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 | }
--------------------------------------------------------------------------------
/Sample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Sample/Assets.xcassets/snapshot.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "snapshot.png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Sample/Assets.xcassets/snapshot.imageset/snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ian-mcdowell/TiltedTabView/30c11397991c5b7a9ab54eb5d372cbcb27e38126/Sample/Assets.xcassets/snapshot.imageset/snapshot.png
--------------------------------------------------------------------------------
/Sample/Assets.xcassets/snapshot_ipad.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "snapshot_ipad.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Sample/Assets.xcassets/snapshot_ipad.imageset/snapshot_ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ian-mcdowell/TiltedTabView/30c11397991c5b7a9ab54eb5d372cbcb27e38126/Sample/Assets.xcassets/snapshot_ipad.imageset/snapshot_ipad.png
--------------------------------------------------------------------------------
/Sample/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 |
29 |
--------------------------------------------------------------------------------
/Sample/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.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UIStatusBarStyle
30 | UIStatusBarStyleLightContent
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 |
--------------------------------------------------------------------------------
/Sample/ViewController.swift:
--------------------------------------------------------------------------------
1 | import TiltedTabView
2 |
3 | class ViewController: TiltedTabViewController {
4 |
5 | var tabs: [String]
6 |
7 | override init() {
8 | self.tabs = ["Tilted", "Tab", "View"]
9 | super.init()
10 |
11 | self.delegate = self
12 | self.dataSource = self
13 | }
14 |
15 | required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
16 |
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 |
20 | self.navigationController?.isNavigationBarHidden = true
21 | self.navigationController?.isToolbarHidden = false
22 | self.navigationController?.toolbar.barStyle = .blackTranslucent
23 | self.toolbarItems = [
24 | UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
25 | UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewTab)),
26 | UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
27 | ]
28 | }
29 |
30 | @objc private func addNewTab() {
31 | self.addTab(atIndex: tabs.count)
32 | }
33 |
34 | override var preferredStatusBarStyle: UIStatusBarStyle {
35 | return .lightContent
36 | }
37 |
38 | }
39 |
40 | extension ViewController: TiltedTabViewControllerDataSource {
41 | func numberOfTabsInTiltedTabViewController() -> Int {
42 | return tabs.count
43 | }
44 |
45 | func snapshotForTab(atIndex index: Int) -> UIImage? {
46 | if UIDevice.current.userInterfaceIdiom == .pad {
47 | return #imageLiteral(resourceName: "snapshot_ipad")
48 | }
49 | return #imageLiteral(resourceName: "snapshot")
50 | }
51 |
52 | func titleForTab(atIndex index: Int) -> String? {
53 | return tabs[index]
54 | }
55 |
56 | func indexForActiveTab() -> Int? {
57 | return nil
58 | }
59 |
60 | func tabAdded(atIndex index: Int) {
61 | tabs.append("Tab")
62 | }
63 |
64 | func tabRemoved(atIndex index: Int) {
65 | tabs.removeLast()
66 | }
67 |
68 | func tabMoved(fromIndex: Int, toIndex: Int) {
69 | let tab = tabs.remove(at: fromIndex)
70 | tabs.insert(tab, at: toIndex)
71 | }
72 |
73 | }
74 |
75 | extension ViewController: TiltedTabViewControllerDelegate {
76 | func tabSelected(atIndex index: Int) {
77 |
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/Sources/Layouts/TiltedTabCollectionViewLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TiltedTabCollectionViewLayout.swift
3 | // TiltedTabView
4 | //
5 | // Copyright © 2017 Ian McDowell. All rights reserved.
6 | //
7 |
8 | import UIKit
9 |
10 | class TiltedTabCollectionViewLayout: UICollectionViewLayout {
11 |
12 | weak var delegate: UICollectionViewDelegate?
13 | weak var dataSource: UICollectionViewDataSource?
14 |
15 | /// Set by the view controller when user adds a tab.
16 | /// When a cell appears, if its index path was equal to this, the animation will differ.
17 | var addingIndexPath: IndexPath?
18 |
19 | /// Set by the view controller when user removes a tab.
20 | /// When a cell disappears, if its index path was equal to this, the animation will differ.
21 | var removingIndexPath: IndexPath?
22 |
23 | override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
24 | return true
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Layouts/TiltedTabGridCollectionViewLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TiltedTabGridCollectionViewLayout.swift
3 | // TiltedTabView
4 | //
5 | // Copyright © 2017 Ian McDowell. All rights reserved.
6 | //
7 |
8 | import UIKit
9 |
10 | class TiltedTabGridCollectionViewLayout: TiltedTabCollectionViewLayout {
11 |
12 | private let maxItemsPerRow: Int = 3
13 | private let minSpacingBetweenItems: CGFloat = 35
14 |
15 | private var layoutAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:]
16 | private var contentHeight: CGFloat = 0
17 |
18 | override func prepare() {
19 | super.prepare()
20 |
21 | layoutAttributes = [:]
22 |
23 | guard let collectionView = collectionView else {
24 | return
25 | }
26 |
27 | var currentHeight: CGFloat = 0
28 |
29 | // Subtract spacing on left/right
30 | let horizontalSpacing = minSpacingBetweenItems
31 | let verticalSpacing = minSpacingBetweenItems
32 | let rowUsableWidth = collectionView.bounds.width - horizontalSpacing
33 | let maxItemWidth = collectionView.bounds.width * 0.8
34 |
35 | for section in 0.. UICollectionViewLayoutAttributes? {
82 | return layoutAttributes[indexPath]
83 | }
84 |
85 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
86 | return layoutAttributes.values.filter { rect.intersects($0.frame) }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Sources/Layouts/TiltedTabTiltedCollectionViewLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TiltedTabTiltedCollectionViewLayout.swift
3 | // TiltedTabView
4 | //
5 | // Copyright © 2017 Ian McDowell. All rights reserved.
6 | //
7 |
8 | import UIKit
9 |
10 | class TiltedTabTiltedCollectionViewLayout: TiltedTabCollectionViewLayout {
11 |
12 | private var layoutAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:]
13 | private var contentHeight: CGFloat = 0
14 |
15 | private let leftRightPadding: CGFloat = 20
16 | private let minimumAngle: CGFloat = -30
17 | private let maximumAngle: CGFloat = -80
18 | private let standardDepth: CGFloat = 200
19 | private let distanceBetweenItems: CGFloat = 123
20 |
21 | internal var currentMotionOffset: UIOffset = UIOffsetMake(0, 0) {
22 | didSet { self.invalidateLayout() }
23 | }
24 |
25 | override func prepare() {
26 | super.prepare()
27 |
28 | layoutAttributes = [:]
29 | contentHeight = 0
30 |
31 | guard let collectionView = collectionView else {
32 | return
33 | }
34 |
35 | let itemWidth = collectionView.bounds.width - (2 * leftRightPadding)
36 | let scaleFactor: CGFloat = itemWidth / collectionView.bounds.width
37 | let itemHeight = collectionView.bounds.height * scaleFactor
38 |
39 | for section in 0.. UICollectionViewLayoutAttributes? {
88 | return layoutAttributes[indexPath]
89 | }
90 |
91 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
92 | return layoutAttributes.values.filter { rect.intersects($0.frame) }
93 | }
94 |
95 | override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
96 | guard let attributes = super.initialLayoutAttributesForAppearingItem(at: itemIndexPath) else { return nil }
97 | if self.addingIndexPath == itemIndexPath {
98 | attributes.transform3D = CATransform3DScale(CATransform3DTranslate(attributes.transform3D, 0, attributes.bounds.height, 0), 0.8, 0.8, 0.8)
99 | }
100 | return attributes
101 | }
102 |
103 | override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
104 | guard let attributes = super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath) else { return nil }
105 | if self.removingIndexPath == itemIndexPath {
106 | attributes.transform3D = CATransform3DTranslate(attributes.transform3D, -attributes.bounds.width, 0, 0)
107 | }
108 | return attributes
109 | }
110 |
111 | override func layoutAttributesForInteractivelyMovingItem(at indexPath: IndexPath, withTargetPosition position: CGPoint) -> UICollectionViewLayoutAttributes {
112 | let attributes = super.layoutAttributesForInteractivelyMovingItem(at: indexPath, withTargetPosition: position)
113 | return attributes
114 | }
115 |
116 | }
117 |
118 | internal extension TiltedTabTiltedCollectionViewLayout {
119 |
120 | func applyMotionEffects(toCollectionView collectionView: UICollectionView) {
121 | for effect in collectionView.motionEffects {
122 | if effect is NotifyingMotionEffect {
123 | collectionView.removeMotionEffect(effect)
124 | }
125 | }
126 |
127 | collectionView.addMotionEffect(NotifyingMotionEffect(layout: self))
128 | }
129 | }
130 |
131 | @objc private class NotifyingMotionEffect: UIMotionEffect {
132 |
133 | private weak var layout: TiltedTabTiltedCollectionViewLayout?
134 | init(layout: TiltedTabTiltedCollectionViewLayout) {
135 | self.layout = layout
136 | super.init()
137 | }
138 |
139 | required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
140 |
141 | override func keyPathsAndRelativeValues(forViewerOffset viewerOffset: UIOffset) -> [String : Any]? {
142 | self.layout?.currentMotionOffset = viewerOffset
143 | return nil
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Sources/TiltedTabViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TiltedTabViewController.swift
3 | // TiltedTabView
4 | //
5 | // Copyright © 2017 Ian McDowell. All rights reserved.
6 | //
7 |
8 | import UIKit
9 |
10 | /// Conform to this data source protocol to provide the tilted tab view data.
11 | public protocol TiltedTabViewControllerDataSource: class {
12 |
13 | /// How many tabs are present in the tab view
14 | func numberOfTabsInTiltedTabViewController() -> Int
15 |
16 | /// Provide an image to display in the tab. Use UIGraphicsImageRenderer to render a view's hierarchy to retrieve a snapshot before presenting the tab view, cache it, and return it here.
17 | func snapshotForTab(atIndex index: Int) -> UIImage?
18 |
19 | /// The title to be displayed on the tab
20 | func titleForTab(atIndex index: Int) -> String?
21 |
22 | /// Used for presentation/dismissal. The tab view will animate the tab at this index in and out.
23 | func indexForActiveTab() -> Int?
24 |
25 | /// Called when a tab was manually added. Add a new tab to data storage.
26 | func tabAdded(atIndex index: Int)
27 |
28 | /// Called when a tab was closed by the user. Remove it from data storage.
29 | func tabRemoved(atIndex index: Int)
30 |
31 | /// Called when a tab was moved by the user. Move it in the data storage.
32 | func tabMoved(fromIndex: Int, toIndex: Int)
33 | }
34 |
35 | /// Conform to this delegate protocol to know when the tilted tab view does things.
36 | public protocol TiltedTabViewControllerDelegate: class {
37 |
38 | /// The user tapped on the tab at the given index.
39 | func tabSelected(atIndex index: Int)
40 |
41 | }
42 |
43 | /// A UICollectionViewController containing a tilted tab view.
44 | /// It should not be necessary to subclass this, as most functionality is exposed through its data source and delegate.
45 | open class TiltedTabViewController: UICollectionViewController {
46 |
47 | public weak var dataSource: TiltedTabViewControllerDataSource?
48 | public weak var delegate: TiltedTabViewControllerDelegate?
49 |
50 | /// Create a new tilted tab view controller.
51 | public init() {
52 | let layout = TiltedTabTiltedCollectionViewLayout()
53 | super.init(collectionViewLayout: layout)
54 | layout.delegate = self
55 | layout.dataSource = self
56 |
57 | self.transitioningDelegate = self
58 | }
59 |
60 | required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
61 |
62 | /// Trigger a reload to the tab content. Data source methods will be called again to re-populate data.
63 | public func reload() {
64 | self.collectionView?.reloadData()
65 | }
66 |
67 | /// Add a new tab at the given index. Be sure to also add a model for this tab to the data source's model.
68 | /// The tabAdded data source method will be called by this method.
69 | public func addTab(atIndex index: Int) {
70 | dataSource?.tabAdded(atIndex: index)
71 | let indexPath = IndexPath(item: index, section: 0)
72 | let layout = self.collectionView?.collectionViewLayout as? TiltedTabCollectionViewLayout
73 | layout?.addingIndexPath = indexPath
74 | self.collectionView?.insertItems(at: [indexPath])
75 | self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
76 | layout?.addingIndexPath = nil
77 | }
78 |
79 | /// Remove the tab at the given index. Be sure to also remove the model for this tab from the data source's model.
80 | /// The tabRemoved data source method will be called by this method.
81 | public func removeTab(atIndex index: Int) {
82 | dataSource?.tabRemoved(atIndex: index)
83 | let indexPath = IndexPath(item: index, section: 0)
84 | let layout = self.collectionView?.collectionViewLayout as? TiltedTabCollectionViewLayout
85 | layout?.removingIndexPath = indexPath
86 | self.collectionView?.deleteItems(at: [indexPath])
87 | layout?.removingIndexPath = nil
88 | }
89 |
90 | // MARK: UIViewController
91 |
92 | open override func viewDidLoad() {
93 | super.viewDidLoad()
94 |
95 | guard let collectionView = self.collectionView else {
96 | assertionFailure("Collection view not found in UICollectionViewController")
97 | return
98 | }
99 | collectionView.backgroundColor = UIColor(white: 0.2, alpha: 1)
100 |
101 | collectionView.alwaysBounceVertical = true
102 | collectionView.dataSource = self
103 | collectionView.delegate = self
104 | collectionView.register(TiltedTabViewCell.self, forCellWithReuseIdentifier: "Tab")
105 |
106 | (collectionView.collectionViewLayout as? TiltedTabTiltedCollectionViewLayout)?.applyMotionEffects(toCollectionView: collectionView)
107 | }
108 |
109 | open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
110 | super.traitCollectionDidChange(previousTraitCollection)
111 |
112 | let layout: TiltedTabCollectionViewLayout
113 | switch self.traitCollection.horizontalSizeClass {
114 | case .compact:
115 | let tiltedLayout = TiltedTabTiltedCollectionViewLayout()
116 | tiltedLayout.applyMotionEffects(toCollectionView: self.collectionView!)
117 | layout = tiltedLayout
118 | case .regular:
119 | layout = TiltedTabGridCollectionViewLayout()
120 | default:
121 | return
122 | }
123 |
124 | layout.delegate = self
125 | layout.dataSource = self
126 | self.collectionView?.collectionViewLayout = layout
127 | }
128 |
129 | open override var preferredStatusBarStyle: UIStatusBarStyle {
130 | return .lightContent
131 | }
132 | }
133 |
134 | // MARK: UICollectionViewDataSource
135 | extension TiltedTabViewController {
136 |
137 | open override func numberOfSections(in collectionView: UICollectionView) -> Int {
138 | return 1
139 | }
140 |
141 | open override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
142 | return dataSource?.numberOfTabsInTiltedTabViewController() ?? 0
143 | }
144 |
145 | open override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
146 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Tab", for: indexPath) as! TiltedTabViewCell
147 |
148 | cell.delegate = self
149 | cell.title = dataSource?.titleForTab(atIndex: indexPath.item)
150 | cell.snapshot = dataSource?.snapshotForTab(atIndex: indexPath.item)
151 |
152 | // Only show gradient if in tilted tab layout
153 | cell.gradientLayer.isHidden = !(self.collectionView?.collectionViewLayout is TiltedTabTiltedCollectionViewLayout)
154 |
155 | return cell
156 | }
157 |
158 | open override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
159 | dataSource?.tabMoved(fromIndex: sourceIndexPath.item, toIndex: destinationIndexPath.item)
160 | }
161 |
162 | open override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
163 | collectionView.deselectItem(at: indexPath, animated: true)
164 |
165 | delegate?.tabSelected(atIndex: indexPath.item)
166 | }
167 | }
168 |
169 | extension TiltedTabViewController: TiltedTabViewCellDelegate {
170 | func tiltedTabViewCellCloseButtonTapped(_ cell: TiltedTabViewCell) {
171 | guard let indexPath = collectionView?.indexPath(for: cell) else {
172 | return
173 | }
174 | self.removeTab(atIndex: indexPath.item)
175 | }
176 | }
177 |
178 | extension TiltedTabViewController: UIViewControllerTransitioningDelegate {
179 |
180 | private class PresentingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
181 |
182 | let tabViewController: TiltedTabViewController?
183 | let activatedTabIndex: Int?
184 |
185 | init(tabViewController: TiltedTabViewController?, activatedTabIndex: Int?) {
186 | self.tabViewController = tabViewController; self.activatedTabIndex = activatedTabIndex
187 | }
188 |
189 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
190 | return 0.5
191 | }
192 |
193 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
194 | guard let toViewController = transitionContext.viewController(forKey: .to) else {
195 | return
196 | }
197 |
198 | let toView = transitionContext.view(forKey: .to)
199 | let fromView = transitionContext.view(forKey: .from)
200 | let fromSnapshot = fromView?.snapshotView(afterScreenUpdates: true)
201 |
202 | let containerView = transitionContext.containerView
203 |
204 | if let toView = toView, let fromView = fromView, let fromSnapshot = fromSnapshot {
205 | containerView.insertSubview(fromSnapshot, aboveSubview: fromView)
206 | containerView.insertSubview(toView, belowSubview: fromSnapshot)
207 | toView.frame = transitionContext.finalFrame(for: toViewController)
208 | }
209 |
210 | let finalPosition: CGRect
211 | let finalTransform: CATransform3D
212 | if
213 | let tabViewController = tabViewController,
214 | let activatedTabIndex = activatedTabIndex,
215 | let layout = tabViewController.collectionViewLayout as? TiltedTabCollectionViewLayout
216 | {
217 | layout.prepare()
218 | let attributes = layout.layoutAttributesForItem(at: IndexPath(item: activatedTabIndex, section: 0))!
219 |
220 | finalPosition = attributes.frame
221 | finalTransform = attributes.transform3D
222 | } else {
223 | // Fall back to a scale transform
224 | finalTransform = CATransform3DMakeScale(0.5, 0.5, 1)
225 | finalPosition = fromView?.frame ?? .zero
226 | }
227 |
228 | toView?.alpha = 0
229 | UIView.animate(withDuration:
230 | self.transitionDuration(using: transitionContext),
231 | delay: 0,
232 | usingSpringWithDamping: 300,
233 | initialSpringVelocity: 5,
234 | options: .allowUserInteraction,
235 | animations: {
236 | toView?.alpha = 1
237 |
238 | fromSnapshot?.layer.transform = finalTransform
239 | fromSnapshot?.frame = finalPosition
240 | fromSnapshot?.alpha = 0
241 | },
242 | completion: { finished in
243 |
244 | let wasCancelled = transitionContext.transitionWasCancelled
245 | transitionContext.completeTransition(!wasCancelled)
246 |
247 | fromSnapshot?.removeFromSuperview()
248 | }
249 | )
250 | }
251 | }
252 |
253 | private class DismissingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
254 |
255 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
256 | return 0.5
257 | }
258 |
259 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
260 | guard let toViewController = transitionContext.viewController(forKey: .to) else {
261 | return
262 | }
263 |
264 | let toView = transitionContext.view(forKey: .to)
265 | let fromView = transitionContext.view(forKey: .from)
266 |
267 | let containerView = transitionContext.containerView
268 |
269 | if let toView = toView {
270 | containerView.addSubview(toView)
271 | toView.frame = transitionContext.finalFrame(for: toViewController)
272 | }
273 |
274 | toView?.alpha = 0
275 | toView?.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
276 | UIView.animate(withDuration:
277 | self.transitionDuration(using: transitionContext),
278 | delay: 0,
279 | usingSpringWithDamping: 300,
280 | initialSpringVelocity: 5,
281 | options: .allowUserInteraction,
282 | animations: {
283 | fromView?.alpha = 0
284 | toView?.alpha = 1
285 | toView?.transform = .identity
286 | },
287 | completion: { finished in
288 |
289 | let wasCancelled = transitionContext.transitionWasCancelled
290 | transitionContext.completeTransition(!wasCancelled)
291 | }
292 | )
293 | }
294 | }
295 |
296 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
297 | return PresentingAnimationController(
298 | tabViewController: presented as? TiltedTabViewController ?? (presented as? UINavigationController)?.childViewControllers.first as? TiltedTabViewController,
299 | activatedTabIndex: (source as? TiltedTabViewControllerDataSource)?.indexForActiveTab()
300 | )
301 | }
302 |
303 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
304 | return DismissingAnimationController()
305 | }
306 |
307 | public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
308 | return nil
309 | }
310 | }
311 |
--------------------------------------------------------------------------------
/Sources/Views/TiltedTabViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TiltedTabViewCell.swift
3 | // TiltedTabView
4 | //
5 | // Copyright © 2017 Ian McDowell. All rights reserved.
6 | //
7 |
8 | import UIKit
9 |
10 | protocol TiltedTabViewCellDelegate: class {
11 | func tiltedTabViewCellCloseButtonTapped(_ cell: TiltedTabViewCell)
12 | }
13 |
14 | class TiltedTabViewCell: UICollectionViewCell {
15 |
16 | private var cornerRadius: CGFloat = 8
17 |
18 | weak var delegate: TiltedTabViewCellDelegate?
19 |
20 | var title: String? {
21 | didSet {
22 | headerView.titleLabel.text = title
23 | }
24 | }
25 | var snapshot: UIImage? {
26 | didSet {
27 | snapshotContainer.image = snapshot
28 | }
29 | }
30 |
31 | private let headerView: TiltedTabViewCell.HeaderView
32 | private let snapshotContainer: UIImageView
33 | let gradientLayer: CAGradientLayer
34 |
35 | override init(frame: CGRect) {
36 | headerView = TiltedTabViewCell.HeaderView()
37 | snapshotContainer = UIImageView()
38 | gradientLayer = CAGradientLayer()
39 | super.init(frame: frame)
40 |
41 | self.layer.shouldRasterize = true
42 | self.layer.rasterizationScale = UIScreen.main.scale
43 |
44 | self.contentView.layer.cornerRadius = cornerRadius
45 | self.contentView.layer.masksToBounds = true
46 | self.backgroundView = UIView()
47 | self.backgroundView?.backgroundColor = .white
48 | self.backgroundView?.layer.cornerRadius = cornerRadius
49 | self.backgroundView?.layer.masksToBounds = true
50 |
51 | let contentView = self.contentView
52 | headerView.translatesAutoresizingMaskIntoConstraints = false
53 | snapshotContainer.translatesAutoresizingMaskIntoConstraints = false
54 | contentView.addSubview(headerView)
55 | contentView.addSubview(snapshotContainer)
56 |
57 | headerView.backgroundColor = .white
58 |
59 | gradientLayer.colors = [UIColor.clear.cgColor, UIColor.init(white: 0, alpha: 0.4).cgColor, UIColor.init(white: 0, alpha: 0.6).cgColor]
60 | gradientLayer.locations = [0, 0.4, 1]
61 | self.snapshotContainer.layer.addSublayer(gradientLayer)
62 | self.contentView.backgroundColor = .black
63 |
64 | headerView.closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
65 |
66 | NSLayoutConstraint.activate([
67 | headerView.topAnchor.constraint(equalTo: contentView.topAnchor),
68 | headerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
69 | headerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
70 | headerView.heightAnchor.constraint(equalToConstant: 25)
71 | ])
72 |
73 | NSLayoutConstraint.activate([
74 | snapshotContainer.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
75 | snapshotContainer.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
76 | snapshotContainer.topAnchor.constraint(equalTo: headerView.bottomAnchor),
77 | snapshotContainer.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
78 | ])
79 | }
80 |
81 | required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
82 |
83 | override var isHighlighted: Bool {
84 | didSet {
85 | let transform = isHighlighted ? CGAffineTransform(scaleX: 1.05, y: 1.05) : .identity
86 | UIView.animate(
87 | withDuration: 0.3,
88 | delay: 0,
89 | usingSpringWithDamping: 500,
90 | initialSpringVelocity: 3,
91 | options: .allowUserInteraction,
92 | animations: {
93 | self.contentView.transform = transform
94 | self.backgroundView?.transform = transform
95 | },
96 | completion: nil
97 | )
98 | }
99 | }
100 |
101 | override func layoutSubviews() {
102 | super.layoutSubviews()
103 | self.gradientLayer.frame = self.snapshotContainer.bounds
104 | }
105 |
106 | override func prepareForReuse() {
107 | super.prepareForReuse()
108 |
109 | title = nil
110 | snapshot = nil
111 | }
112 |
113 | @objc private func closeTapped() {
114 | self.delegate?.tiltedTabViewCellCloseButtonTapped(self)
115 | }
116 |
117 | class HeaderView: UIView {
118 | let closeButton: UIButton
119 | let titleLabel: UILabel
120 |
121 | init() {
122 | closeButton = UIButton(type: .system)
123 | titleLabel = UILabel()
124 | super.init(frame: .zero)
125 |
126 | closeButton.setImage(HeaderView.closeImage, for: .normal)
127 | closeButton.tintColor = .black
128 |
129 | titleLabel.text = ""
130 | titleLabel.textAlignment = .center
131 | titleLabel.font = UIFont.systemFont(ofSize: 15, weight: .semibold)
132 |
133 | closeButton.translatesAutoresizingMaskIntoConstraints = false
134 | titleLabel.translatesAutoresizingMaskIntoConstraints = false
135 | addSubview(closeButton)
136 | addSubview(titleLabel)
137 |
138 | NSLayoutConstraint.activate([
139 | closeButton.widthAnchor.constraint(equalTo: closeButton.heightAnchor),
140 | closeButton.leadingAnchor.constraint(equalTo: leadingAnchor),
141 | closeButton.topAnchor.constraint(equalTo: topAnchor),
142 | closeButton.bottomAnchor.constraint(equalTo: bottomAnchor)
143 | ])
144 |
145 | NSLayoutConstraint.activate([
146 | titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
147 | titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
148 | titleLabel.topAnchor.constraint(equalTo: topAnchor),
149 | titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor)
150 | ])
151 | }
152 |
153 | required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
154 |
155 | private static var closeImage: UIImage = {
156 | return UIGraphicsImageRenderer(size: CGSize(width: 12, height: 12)).image(actions: { context in
157 | let downwards = UIBezierPath()
158 | downwards.move(to: CGPoint(x: 1, y: 1))
159 | downwards.addLine(to: CGPoint(x: 11, y: 11))
160 | UIColor.black.setStroke()
161 | downwards.lineWidth = 2
162 | downwards.stroke()
163 |
164 | let upwards = UIBezierPath()
165 | upwards.move(to: CGPoint(x: 1, y: 11))
166 | upwards.addLine(to: CGPoint(x: 11, y: 1))
167 | UIColor.black.setStroke()
168 | upwards.lineWidth = 2
169 | upwards.stroke()
170 |
171 | context.cgContext.addPath(downwards.cgPath)
172 | context.cgContext.addPath(upwards.cgPath)
173 | })
174 | }()
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/TiltedTabView.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint InputAssistant.podspec' to ensure this is a
3 | # valid spec and to remove all comments including this before submitting the spec.
4 | #
5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 |
9 | Pod::Spec.new do |s|
10 |
11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
12 | #
13 | # These will help people to find your library, and whilst it
14 | # can feel like a chore to fill in it's definitely to your advantage. The
15 | # summary should be tweet-length, and the description more in depth.
16 | #
17 |
18 | s.name = "TiltedTabView"
19 | s.version = "1.0.0"
20 | s.summary = "This library aims to replicate the tab switcher in Safari on iOS. It handles both compact width (tilted) and regular width (grid) layouts."
21 |
22 | # This description is used to generate tags and improve search results.
23 | # * Think: What does it do? Why did you write it? What is the focus?
24 | # * Try to keep it short, snappy and to the point.
25 | # * Write the description between the DESC delimiters below.
26 | # * Finally, don't worry about the indent, CocoaPods strips it!
27 | s.description = <<-DESC
28 | TiltedTabView 1.0.0 - This library aims to replicate the tab switcher in Safari on iOS. It handles both compact width (tilted) and regular width (grid) layouts.
29 | DESC
30 |
31 | s.homepage = "https://github.com/IMcD23/TiltedTabView"
32 | s.screenshots = "https://github.com/IMcD23/TiltedTabView/raw/master/Resources/Screenshot.png","https://github.com/IMcD23/TiltedTabView/raw/master/Resources/Screenshot_iPad.png"
33 |
34 |
35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
36 | #
37 | # Licensing your code is important. See http://choosealicense.com for more info.
38 | # CocoaPods will detect a license file if there is a named LICENSE*
39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
40 | #
41 |
42 | s.license = { :type => "MIT", :file => "LICENSE" }
43 |
44 |
45 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
46 | #
47 | # Specify the authors of the library, with email addresses. Email addresses
48 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
49 | # accepts just a name if you'd rather not provide an email address.
50 | #
51 | # Specify a social_media_url where others can refer to, for example a twitter
52 | # profile URL.
53 | #
54 |
55 | s.author = { "Ian McDowell" => "me@ianmcdowell.net" }
56 | # Or just: s.author = "Ian McDowell"
57 | # s.authors = { "Ian McDowell" => "me@ianmcdowell.net" }
58 | s.social_media_url = "http://twitter.com/ian_mcdowell"
59 |
60 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
61 | #
62 | # If this Pod runs only on iOS or OS X, then specify the platform and
63 | # the deployment target. You can optionally include the target after the platform.
64 | #
65 |
66 | s.platform = :ios, "10.0"
67 | # s.platform = :ios, "5.0"
68 |
69 | # When using multiple platforms
70 | # s.ios.deployment_target = "5.0"
71 | # s.osx.deployment_target = "10.7"
72 | # s.watchos.deployment_target = "2.0"
73 | # s.tvos.deployment_target = "9.0"
74 |
75 |
76 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
77 | #
78 | # Specify the location from where the source should be retrieved.
79 | # Supports git, hg, bzr, svn and HTTP.
80 | #
81 |
82 | s.source = { :git => "https://github.com/IMcD23/TiltedTabView.git", :tag => "#{s.version}" }
83 |
84 |
85 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
86 | #
87 | # CocoaPods is smart about how it includes source code. For source files
88 | # giving a folder will include any swift, h, m, mm, c & cpp files.
89 | # For header files it will include any header in the folder.
90 | # Not including the public_header_files will make all headers public.
91 | #
92 |
93 | s.source_files = "Sources/**/*.swift"
94 |
95 |
96 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
97 | #
98 | # A list of resources included with the Pod. These are copied into the
99 | # target bundle with a build phase script. Anything else will be cleaned.
100 | # You can preserve files from being cleaned, please don't preserve
101 | # non-essential files like tests, examples and documentation.
102 | #
103 |
104 | # s.resource = "icon.png"
105 | # s.resources = "Resources/*.png"
106 |
107 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
108 |
109 |
110 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
111 | #
112 | # Link your library with frameworks, or libraries. Libraries do not include
113 | # the lib prefix of their name.
114 | #
115 |
116 | # s.framework = "SomeFramework"
117 | # s.frameworks = "SomeFramework", "AnotherFramework"
118 |
119 | # s.library = "iconv"
120 | # s.libraries = "iconv", "xml2"
121 |
122 |
123 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
124 | #
125 | # If your library depends on compiler flags you can set them in the xcconfig hash
126 | # where they will only apply to your library. If you depend on other Podspecs
127 | # you can include multiple dependencies to ensure it works.
128 |
129 | s.requires_arc = true
130 | s.swift_version = "4.0"
131 |
132 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
133 | # s.dependency "JSONKit", "~> 1.4"
134 |
135 | end
136 |
--------------------------------------------------------------------------------
/TiltedTabView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3C13AC28201AF74B002F36B2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C13AC27201AF74B002F36B2 /* ViewController.swift */; };
11 | 3C13AC2A201AF74B002F36B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C13AC29201AF74B002F36B2 /* AppDelegate.swift */; };
12 | 3C13AC2F201AF74B002F36B2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3C13AC2E201AF74B002F36B2 /* Assets.xcassets */; };
13 | 3C13AC32201AF74B002F36B2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3C13AC30201AF74B002F36B2 /* LaunchScreen.storyboard */; };
14 | 3C13AC3A201AF7C9002F36B2 /* TiltedTabView.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 3CB476881FF775C400C6B265 /* TiltedTabView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
15 | 3CB476AC1FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A61FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift */; };
16 | 3CB476AD1FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A71FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift */; };
17 | 3CB476AE1FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A81FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift */; };
18 | 3CB476AF1FF7769900C6B265 /* TiltedTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A91FF7769900C6B265 /* TiltedTabViewController.swift */; };
19 | 3CB476B01FF7769900C6B265 /* TiltedTabViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476AB1FF7769900C6B265 /* TiltedTabViewCell.swift */; };
20 | 3CB476B31FF776EB00C6B265 /* TiltedTabView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CB476B11FF776E200C6B265 /* TiltedTabView.h */; settings = {ATTRIBUTES = (Public, ); }; };
21 | 3CB476B91FF77B7500C6B265 /* TiltedTabCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A61FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift */; };
22 | 3CB476BA1FF77B7500C6B265 /* TiltedTabTiltedCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A71FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift */; };
23 | 3CB476BB1FF77B7500C6B265 /* TiltedTabGridCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A81FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift */; };
24 | 3CB476BC1FF77B7500C6B265 /* TiltedTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476A91FF7769900C6B265 /* TiltedTabViewController.swift */; };
25 | 3CB476BD1FF77B7700C6B265 /* TiltedTabViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB476AB1FF7769900C6B265 /* TiltedTabViewCell.swift */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXContainerItemProxy section */
29 | 3C13AC37201AF78D002F36B2 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 3CB4767F1FF775C400C6B265 /* Project object */;
32 | proxyType = 1;
33 | remoteGlobalIDString = 3CB476871FF775C400C6B265;
34 | remoteInfo = TiltedTabView;
35 | };
36 | /* End PBXContainerItemProxy section */
37 |
38 | /* Begin PBXCopyFilesBuildPhase section */
39 | 3C13AC39201AF7BF002F36B2 /* Copy Frameworks */ = {
40 | isa = PBXCopyFilesBuildPhase;
41 | buildActionMask = 2147483647;
42 | dstPath = "";
43 | dstSubfolderSpec = 10;
44 | files = (
45 | 3C13AC3A201AF7C9002F36B2 /* TiltedTabView.framework in Copy Frameworks */,
46 | );
47 | name = "Copy Frameworks";
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | 3CB476951FF7761400C6B265 /* CopyFiles */ = {
51 | isa = PBXCopyFilesBuildPhase;
52 | buildActionMask = 2147483647;
53 | dstPath = "include/$(PRODUCT_NAME)";
54 | dstSubfolderSpec = 16;
55 | files = (
56 | );
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | /* End PBXCopyFilesBuildPhase section */
60 |
61 | /* Begin PBXFileReference section */
62 | 3C13AC25201AF74B002F36B2 /* TiltedTabView Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TiltedTabView Sample.app"; sourceTree = BUILT_PRODUCTS_DIR; };
63 | 3C13AC27201AF74B002F36B2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
64 | 3C13AC29201AF74B002F36B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
65 | 3C13AC2E201AF74B002F36B2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
66 | 3C13AC31201AF74B002F36B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
67 | 3C13AC33201AF74B002F36B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
68 | 3CB476881FF775C400C6B265 /* TiltedTabView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TiltedTabView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
69 | 3CB4768C1FF775C400C6B265 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
70 | 3CB476971FF7761400C6B265 /* libTiltedTabView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTiltedTabView.a; sourceTree = BUILT_PRODUCTS_DIR; };
71 | 3CB476A61FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TiltedTabCollectionViewLayout.swift; sourceTree = ""; };
72 | 3CB476A71FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TiltedTabTiltedCollectionViewLayout.swift; sourceTree = ""; };
73 | 3CB476A81FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TiltedTabGridCollectionViewLayout.swift; sourceTree = ""; };
74 | 3CB476A91FF7769900C6B265 /* TiltedTabViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TiltedTabViewController.swift; sourceTree = ""; };
75 | 3CB476AB1FF7769900C6B265 /* TiltedTabViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TiltedTabViewCell.swift; sourceTree = ""; };
76 | 3CB476B11FF776E200C6B265 /* TiltedTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiltedTabView.h; sourceTree = ""; };
77 | /* End PBXFileReference section */
78 |
79 | /* Begin PBXFrameworksBuildPhase section */
80 | 3C13AC22201AF74B002F36B2 /* Frameworks */ = {
81 | isa = PBXFrameworksBuildPhase;
82 | buildActionMask = 2147483647;
83 | files = (
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | 3CB476841FF775C400C6B265 /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | 3CB476941FF7761400C6B265 /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | /* End PBXFrameworksBuildPhase section */
102 |
103 | /* Begin PBXGroup section */
104 | 3C13AC26201AF74B002F36B2 /* Sample */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 3C13AC27201AF74B002F36B2 /* ViewController.swift */,
108 | 3C13AC29201AF74B002F36B2 /* AppDelegate.swift */,
109 | 3C13AC2E201AF74B002F36B2 /* Assets.xcassets */,
110 | 3C13AC30201AF74B002F36B2 /* LaunchScreen.storyboard */,
111 | 3C13AC33201AF74B002F36B2 /* Info.plist */,
112 | );
113 | path = Sample;
114 | sourceTree = "";
115 | };
116 | 3CB4767E1FF775C400C6B265 = {
117 | isa = PBXGroup;
118 | children = (
119 | 3CB476A41FF7767400C6B265 /* Sources */,
120 | 3CB4768A1FF775C400C6B265 /* Framework */,
121 | 3C13AC26201AF74B002F36B2 /* Sample */,
122 | 3CB476891FF775C400C6B265 /* Products */,
123 | 3CB476A21FF7765D00C6B265 /* Frameworks */,
124 | );
125 | sourceTree = "";
126 | usesTabs = 0;
127 | };
128 | 3CB476891FF775C400C6B265 /* Products */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 3CB476881FF775C400C6B265 /* TiltedTabView.framework */,
132 | 3CB476971FF7761400C6B265 /* libTiltedTabView.a */,
133 | 3C13AC25201AF74B002F36B2 /* TiltedTabView Sample.app */,
134 | );
135 | name = Products;
136 | sourceTree = "";
137 | };
138 | 3CB4768A1FF775C400C6B265 /* Framework */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 3CB476B11FF776E200C6B265 /* TiltedTabView.h */,
142 | 3CB4768C1FF775C400C6B265 /* Info.plist */,
143 | );
144 | path = Framework;
145 | sourceTree = "";
146 | };
147 | 3CB476A21FF7765D00C6B265 /* Frameworks */ = {
148 | isa = PBXGroup;
149 | children = (
150 | );
151 | name = Frameworks;
152 | sourceTree = "";
153 | };
154 | 3CB476A41FF7767400C6B265 /* Sources */ = {
155 | isa = PBXGroup;
156 | children = (
157 | 3CB476A51FF7769900C6B265 /* Layouts */,
158 | 3CB476A91FF7769900C6B265 /* TiltedTabViewController.swift */,
159 | 3CB476AA1FF7769900C6B265 /* Views */,
160 | );
161 | path = Sources;
162 | sourceTree = "";
163 | };
164 | 3CB476A51FF7769900C6B265 /* Layouts */ = {
165 | isa = PBXGroup;
166 | children = (
167 | 3CB476A61FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift */,
168 | 3CB476A71FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift */,
169 | 3CB476A81FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift */,
170 | );
171 | path = Layouts;
172 | sourceTree = "";
173 | };
174 | 3CB476AA1FF7769900C6B265 /* Views */ = {
175 | isa = PBXGroup;
176 | children = (
177 | 3CB476AB1FF7769900C6B265 /* TiltedTabViewCell.swift */,
178 | );
179 | path = Views;
180 | sourceTree = "";
181 | };
182 | /* End PBXGroup section */
183 |
184 | /* Begin PBXHeadersBuildPhase section */
185 | 3CB476B21FF776E700C6B265 /* Headers */ = {
186 | isa = PBXHeadersBuildPhase;
187 | buildActionMask = 2147483647;
188 | files = (
189 | 3CB476B31FF776EB00C6B265 /* TiltedTabView.h in Headers */,
190 | );
191 | runOnlyForDeploymentPostprocessing = 0;
192 | };
193 | /* End PBXHeadersBuildPhase section */
194 |
195 | /* Begin PBXNativeTarget section */
196 | 3C13AC24201AF74B002F36B2 /* TiltedTabView Sample */ = {
197 | isa = PBXNativeTarget;
198 | buildConfigurationList = 3C13AC36201AF74B002F36B2 /* Build configuration list for PBXNativeTarget "TiltedTabView Sample" */;
199 | buildPhases = (
200 | 3C13AC21201AF74B002F36B2 /* Sources */,
201 | 3C13AC22201AF74B002F36B2 /* Frameworks */,
202 | 3C13AC23201AF74B002F36B2 /* Resources */,
203 | 3C13AC39201AF7BF002F36B2 /* Copy Frameworks */,
204 | );
205 | buildRules = (
206 | );
207 | dependencies = (
208 | 3C13AC38201AF78D002F36B2 /* PBXTargetDependency */,
209 | );
210 | name = "TiltedTabView Sample";
211 | productName = "TiltedTabView Sample";
212 | productReference = 3C13AC25201AF74B002F36B2 /* TiltedTabView Sample.app */;
213 | productType = "com.apple.product-type.application";
214 | };
215 | 3CB476871FF775C400C6B265 /* TiltedTabView */ = {
216 | isa = PBXNativeTarget;
217 | buildConfigurationList = 3CB476901FF775C400C6B265 /* Build configuration list for PBXNativeTarget "TiltedTabView" */;
218 | buildPhases = (
219 | 3CB476831FF775C400C6B265 /* Sources */,
220 | 3CB476841FF775C400C6B265 /* Frameworks */,
221 | 3CB476B21FF776E700C6B265 /* Headers */,
222 | );
223 | buildRules = (
224 | );
225 | dependencies = (
226 | );
227 | name = TiltedTabView;
228 | productName = TiltedTabView;
229 | productReference = 3CB476881FF775C400C6B265 /* TiltedTabView.framework */;
230 | productType = "com.apple.product-type.framework";
231 | };
232 | 3CB476961FF7761400C6B265 /* libTiltedTabView */ = {
233 | isa = PBXNativeTarget;
234 | buildConfigurationList = 3CB4769D1FF7761400C6B265 /* Build configuration list for PBXNativeTarget "libTiltedTabView" */;
235 | buildPhases = (
236 | 3CB476931FF7761400C6B265 /* Sources */,
237 | 3CB476941FF7761400C6B265 /* Frameworks */,
238 | 3CB476951FF7761400C6B265 /* CopyFiles */,
239 | );
240 | buildRules = (
241 | );
242 | dependencies = (
243 | );
244 | name = libTiltedTabView;
245 | productName = libTiltedTabView;
246 | productReference = 3CB476971FF7761400C6B265 /* libTiltedTabView.a */;
247 | productType = "com.apple.product-type.library.static";
248 | };
249 | /* End PBXNativeTarget section */
250 |
251 | /* Begin PBXProject section */
252 | 3CB4767F1FF775C400C6B265 /* Project object */ = {
253 | isa = PBXProject;
254 | attributes = {
255 | LastSwiftUpdateCheck = 0920;
256 | LastUpgradeCheck = 0920;
257 | ORGANIZATIONNAME = "Ian McDowell";
258 | TargetAttributes = {
259 | 3C13AC24201AF74B002F36B2 = {
260 | CreatedOnToolsVersion = 9.2;
261 | };
262 | 3CB476871FF775C400C6B265 = {
263 | CreatedOnToolsVersion = 9.2;
264 | ProvisioningStyle = Automatic;
265 | };
266 | 3CB476961FF7761400C6B265 = {
267 | CreatedOnToolsVersion = 9.2;
268 | LastSwiftMigration = 0920;
269 | };
270 | };
271 | };
272 | buildConfigurationList = 3CB476821FF775C400C6B265 /* Build configuration list for PBXProject "TiltedTabView" */;
273 | compatibilityVersion = "Xcode 8.0";
274 | developmentRegion = en;
275 | hasScannedForEncodings = 0;
276 | knownRegions = (
277 | en,
278 | Base,
279 | );
280 | mainGroup = 3CB4767E1FF775C400C6B265;
281 | productRefGroup = 3CB476891FF775C400C6B265 /* Products */;
282 | projectDirPath = "";
283 | projectRoot = "";
284 | targets = (
285 | 3CB476871FF775C400C6B265 /* TiltedTabView */,
286 | 3CB476961FF7761400C6B265 /* libTiltedTabView */,
287 | 3C13AC24201AF74B002F36B2 /* TiltedTabView Sample */,
288 | );
289 | };
290 | /* End PBXProject section */
291 |
292 | /* Begin PBXResourcesBuildPhase section */
293 | 3C13AC23201AF74B002F36B2 /* Resources */ = {
294 | isa = PBXResourcesBuildPhase;
295 | buildActionMask = 2147483647;
296 | files = (
297 | 3C13AC32201AF74B002F36B2 /* LaunchScreen.storyboard in Resources */,
298 | 3C13AC2F201AF74B002F36B2 /* Assets.xcassets in Resources */,
299 | );
300 | runOnlyForDeploymentPostprocessing = 0;
301 | };
302 | /* End PBXResourcesBuildPhase section */
303 |
304 | /* Begin PBXSourcesBuildPhase section */
305 | 3C13AC21201AF74B002F36B2 /* Sources */ = {
306 | isa = PBXSourcesBuildPhase;
307 | buildActionMask = 2147483647;
308 | files = (
309 | 3C13AC2A201AF74B002F36B2 /* AppDelegate.swift in Sources */,
310 | 3C13AC28201AF74B002F36B2 /* ViewController.swift in Sources */,
311 | );
312 | runOnlyForDeploymentPostprocessing = 0;
313 | };
314 | 3CB476831FF775C400C6B265 /* Sources */ = {
315 | isa = PBXSourcesBuildPhase;
316 | buildActionMask = 2147483647;
317 | files = (
318 | 3CB476BC1FF77B7500C6B265 /* TiltedTabViewController.swift in Sources */,
319 | 3CB476BA1FF77B7500C6B265 /* TiltedTabTiltedCollectionViewLayout.swift in Sources */,
320 | 3CB476BD1FF77B7700C6B265 /* TiltedTabViewCell.swift in Sources */,
321 | 3CB476BB1FF77B7500C6B265 /* TiltedTabGridCollectionViewLayout.swift in Sources */,
322 | 3CB476B91FF77B7500C6B265 /* TiltedTabCollectionViewLayout.swift in Sources */,
323 | );
324 | runOnlyForDeploymentPostprocessing = 0;
325 | };
326 | 3CB476931FF7761400C6B265 /* Sources */ = {
327 | isa = PBXSourcesBuildPhase;
328 | buildActionMask = 2147483647;
329 | files = (
330 | 3CB476AF1FF7769900C6B265 /* TiltedTabViewController.swift in Sources */,
331 | 3CB476AD1FF7769900C6B265 /* TiltedTabTiltedCollectionViewLayout.swift in Sources */,
332 | 3CB476B01FF7769900C6B265 /* TiltedTabViewCell.swift in Sources */,
333 | 3CB476AE1FF7769900C6B265 /* TiltedTabGridCollectionViewLayout.swift in Sources */,
334 | 3CB476AC1FF7769900C6B265 /* TiltedTabCollectionViewLayout.swift in Sources */,
335 | );
336 | runOnlyForDeploymentPostprocessing = 0;
337 | };
338 | /* End PBXSourcesBuildPhase section */
339 |
340 | /* Begin PBXTargetDependency section */
341 | 3C13AC38201AF78D002F36B2 /* PBXTargetDependency */ = {
342 | isa = PBXTargetDependency;
343 | target = 3CB476871FF775C400C6B265 /* TiltedTabView */;
344 | targetProxy = 3C13AC37201AF78D002F36B2 /* PBXContainerItemProxy */;
345 | };
346 | /* End PBXTargetDependency section */
347 |
348 | /* Begin PBXVariantGroup section */
349 | 3C13AC30201AF74B002F36B2 /* LaunchScreen.storyboard */ = {
350 | isa = PBXVariantGroup;
351 | children = (
352 | 3C13AC31201AF74B002F36B2 /* Base */,
353 | );
354 | name = LaunchScreen.storyboard;
355 | sourceTree = "";
356 | };
357 | /* End PBXVariantGroup section */
358 |
359 | /* Begin XCBuildConfiguration section */
360 | 3C13AC34201AF74B002F36B2 /* Debug */ = {
361 | isa = XCBuildConfiguration;
362 | buildSettings = {
363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
364 | INFOPLIST_FILE = "$(SRCROOT)/Sample/Info.plist";
365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
366 | PRODUCT_BUNDLE_IDENTIFIER = "net.ianmcdowell.TiltedTabView-Sample";
367 | PRODUCT_NAME = "$(TARGET_NAME)";
368 | SWIFT_VERSION = 4.0;
369 | };
370 | name = Debug;
371 | };
372 | 3C13AC35201AF74B002F36B2 /* Release */ = {
373 | isa = XCBuildConfiguration;
374 | buildSettings = {
375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
376 | INFOPLIST_FILE = "$(SRCROOT)/Sample/Info.plist";
377 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
378 | PRODUCT_BUNDLE_IDENTIFIER = "net.ianmcdowell.TiltedTabView-Sample";
379 | PRODUCT_NAME = "$(TARGET_NAME)";
380 | SWIFT_VERSION = 4.0;
381 | };
382 | name = Release;
383 | };
384 | 3CB4768E1FF775C400C6B265 /* Debug */ = {
385 | isa = XCBuildConfiguration;
386 | buildSettings = {
387 | ALWAYS_SEARCH_USER_PATHS = NO;
388 | CLANG_ANALYZER_NONNULL = YES;
389 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
390 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
391 | CLANG_CXX_LIBRARY = "libc++";
392 | CLANG_ENABLE_MODULES = YES;
393 | CLANG_ENABLE_OBJC_ARC = YES;
394 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
395 | CLANG_WARN_BOOL_CONVERSION = YES;
396 | CLANG_WARN_COMMA = YES;
397 | CLANG_WARN_CONSTANT_CONVERSION = YES;
398 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
399 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
400 | CLANG_WARN_EMPTY_BODY = YES;
401 | CLANG_WARN_ENUM_CONVERSION = YES;
402 | CLANG_WARN_INFINITE_RECURSION = YES;
403 | CLANG_WARN_INT_CONVERSION = YES;
404 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
405 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
406 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
407 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
408 | CLANG_WARN_STRICT_PROTOTYPES = YES;
409 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
410 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
411 | CLANG_WARN_UNREACHABLE_CODE = YES;
412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
413 | CODE_SIGN_IDENTITY = "";
414 | COPY_PHASE_STRIP = NO;
415 | CURRENT_PROJECT_VERSION = 1;
416 | DEBUG_INFORMATION_FORMAT = dwarf;
417 | ENABLE_STRICT_OBJC_MSGSEND = YES;
418 | ENABLE_TESTABILITY = YES;
419 | GCC_C_LANGUAGE_STANDARD = gnu11;
420 | GCC_DYNAMIC_NO_PIC = NO;
421 | GCC_NO_COMMON_BLOCKS = YES;
422 | GCC_OPTIMIZATION_LEVEL = 0;
423 | GCC_PREPROCESSOR_DEFINITIONS = (
424 | "DEBUG=1",
425 | "$(inherited)",
426 | );
427 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
428 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
429 | GCC_WARN_UNDECLARED_SELECTOR = YES;
430 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
431 | GCC_WARN_UNUSED_FUNCTION = YES;
432 | GCC_WARN_UNUSED_VARIABLE = YES;
433 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
434 | MTL_ENABLE_DEBUG_INFO = YES;
435 | ONLY_ACTIVE_ARCH = YES;
436 | SDKROOT = iphoneos;
437 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
438 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
439 | SWIFT_VERSION = 4.0;
440 | TARGETED_DEVICE_FAMILY = "1,2";
441 | VERSIONING_SYSTEM = "apple-generic";
442 | VERSION_INFO_PREFIX = "";
443 | };
444 | name = Debug;
445 | };
446 | 3CB4768F1FF775C400C6B265 /* Release */ = {
447 | isa = XCBuildConfiguration;
448 | buildSettings = {
449 | ALWAYS_SEARCH_USER_PATHS = NO;
450 | CLANG_ANALYZER_NONNULL = YES;
451 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
452 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
453 | CLANG_CXX_LIBRARY = "libc++";
454 | CLANG_ENABLE_MODULES = YES;
455 | CLANG_ENABLE_OBJC_ARC = YES;
456 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
457 | CLANG_WARN_BOOL_CONVERSION = YES;
458 | CLANG_WARN_COMMA = YES;
459 | CLANG_WARN_CONSTANT_CONVERSION = YES;
460 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
461 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
462 | CLANG_WARN_EMPTY_BODY = YES;
463 | CLANG_WARN_ENUM_CONVERSION = YES;
464 | CLANG_WARN_INFINITE_RECURSION = YES;
465 | CLANG_WARN_INT_CONVERSION = YES;
466 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
467 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
468 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
469 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
470 | CLANG_WARN_STRICT_PROTOTYPES = YES;
471 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
472 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
473 | CLANG_WARN_UNREACHABLE_CODE = YES;
474 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
475 | CODE_SIGN_IDENTITY = "";
476 | COPY_PHASE_STRIP = NO;
477 | CURRENT_PROJECT_VERSION = 1;
478 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
479 | ENABLE_NS_ASSERTIONS = NO;
480 | ENABLE_STRICT_OBJC_MSGSEND = YES;
481 | GCC_C_LANGUAGE_STANDARD = gnu11;
482 | GCC_NO_COMMON_BLOCKS = YES;
483 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
484 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
485 | GCC_WARN_UNDECLARED_SELECTOR = YES;
486 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
487 | GCC_WARN_UNUSED_FUNCTION = YES;
488 | GCC_WARN_UNUSED_VARIABLE = YES;
489 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
490 | MTL_ENABLE_DEBUG_INFO = NO;
491 | SDKROOT = iphoneos;
492 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
493 | SWIFT_VERSION = 4.0;
494 | TARGETED_DEVICE_FAMILY = "1,2";
495 | VALIDATE_PRODUCT = YES;
496 | VERSIONING_SYSTEM = "apple-generic";
497 | VERSION_INFO_PREFIX = "";
498 | };
499 | name = Release;
500 | };
501 | 3CB476911FF775C400C6B265 /* Debug */ = {
502 | isa = XCBuildConfiguration;
503 | buildSettings = {
504 | APPLICATION_EXTENSION_API_ONLY = YES;
505 | DEFINES_MODULE = YES;
506 | DYLIB_COMPATIBILITY_VERSION = 1;
507 | DYLIB_CURRENT_VERSION = 1;
508 | DYLIB_INSTALL_NAME_BASE = "@rpath";
509 | INFOPLIST_FILE = Framework/Info.plist;
510 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
511 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
512 | LIBRARY_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)";
513 | PRODUCT_BUNDLE_IDENTIFIER = net.ianmcdowell.TiltedTabView;
514 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
515 | SKIP_INSTALL = YES;
516 | };
517 | name = Debug;
518 | };
519 | 3CB476921FF775C400C6B265 /* Release */ = {
520 | isa = XCBuildConfiguration;
521 | buildSettings = {
522 | APPLICATION_EXTENSION_API_ONLY = YES;
523 | DEFINES_MODULE = YES;
524 | DYLIB_COMPATIBILITY_VERSION = 1;
525 | DYLIB_CURRENT_VERSION = 1;
526 | DYLIB_INSTALL_NAME_BASE = "@rpath";
527 | INFOPLIST_FILE = Framework/Info.plist;
528 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
529 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
530 | LIBRARY_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)";
531 | PRODUCT_BUNDLE_IDENTIFIER = net.ianmcdowell.TiltedTabView;
532 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
533 | SKIP_INSTALL = YES;
534 | };
535 | name = Release;
536 | };
537 | 3CB4769E1FF7761400C6B265 /* Debug */ = {
538 | isa = XCBuildConfiguration;
539 | buildSettings = {
540 | APPLICATION_EXTENSION_API_ONLY = YES;
541 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
542 | OTHER_LDFLAGS = "-ObjC";
543 | PRODUCT_NAME = TiltedTabView;
544 | SKIP_INSTALL = YES;
545 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
546 | };
547 | name = Debug;
548 | };
549 | 3CB4769F1FF7761400C6B265 /* Release */ = {
550 | isa = XCBuildConfiguration;
551 | buildSettings = {
552 | APPLICATION_EXTENSION_API_ONLY = YES;
553 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
554 | OTHER_LDFLAGS = "-ObjC";
555 | PRODUCT_NAME = TiltedTabView;
556 | SKIP_INSTALL = YES;
557 | };
558 | name = Release;
559 | };
560 | /* End XCBuildConfiguration section */
561 |
562 | /* Begin XCConfigurationList section */
563 | 3C13AC36201AF74B002F36B2 /* Build configuration list for PBXNativeTarget "TiltedTabView Sample" */ = {
564 | isa = XCConfigurationList;
565 | buildConfigurations = (
566 | 3C13AC34201AF74B002F36B2 /* Debug */,
567 | 3C13AC35201AF74B002F36B2 /* Release */,
568 | );
569 | defaultConfigurationIsVisible = 0;
570 | defaultConfigurationName = Release;
571 | };
572 | 3CB476821FF775C400C6B265 /* Build configuration list for PBXProject "TiltedTabView" */ = {
573 | isa = XCConfigurationList;
574 | buildConfigurations = (
575 | 3CB4768E1FF775C400C6B265 /* Debug */,
576 | 3CB4768F1FF775C400C6B265 /* Release */,
577 | );
578 | defaultConfigurationIsVisible = 0;
579 | defaultConfigurationName = Release;
580 | };
581 | 3CB476901FF775C400C6B265 /* Build configuration list for PBXNativeTarget "TiltedTabView" */ = {
582 | isa = XCConfigurationList;
583 | buildConfigurations = (
584 | 3CB476911FF775C400C6B265 /* Debug */,
585 | 3CB476921FF775C400C6B265 /* Release */,
586 | );
587 | defaultConfigurationIsVisible = 0;
588 | defaultConfigurationName = Release;
589 | };
590 | 3CB4769D1FF7761400C6B265 /* Build configuration list for PBXNativeTarget "libTiltedTabView" */ = {
591 | isa = XCConfigurationList;
592 | buildConfigurations = (
593 | 3CB4769E1FF7761400C6B265 /* Debug */,
594 | 3CB4769F1FF7761400C6B265 /* Release */,
595 | );
596 | defaultConfigurationIsVisible = 0;
597 | defaultConfigurationName = Release;
598 | };
599 | /* End XCConfigurationList section */
600 | };
601 | rootObject = 3CB4767F1FF775C400C6B265 /* Project object */;
602 | }
603 |
--------------------------------------------------------------------------------
/TiltedTabView.xcodeproj/xcshareddata/xcschemes/TiltedTabView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
72 |
73 |
74 |
75 |
77 |
78 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/TiltedTabView.xcodeproj/xcshareddata/xcschemes/libTiltedTabView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
72 |
73 |
74 |
75 |
77 |
78 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/build.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | TiltedTabView
7 | build
8 |
9 | buildSystem
10 | xcode
11 | buildArgs
12 |
13 | -project
14 | TiltedTabView.xcodeproj
15 | -target
16 | libTiltedTabView
17 |
18 | outputs
19 |
20 | libTiltedTabView.a
21 |
22 |
23 | dependencies
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------