From 21ca6cc08a546e5dda6fd24df8dd788026a2dc11 Mon Sep 17 00:00:00 2001 From: pera Date: Fri, 5 May 2017 15:51:39 -0300 Subject: [PATCH 1/2] Add swiftlint & fixes --- .swiftlint.yml | 51 +++++ Example/Example/AppDelegate.swift | 11 +- .../Example/BarExampleViewController.swift | 27 ++- .../ButtonBarExampleViewController.swift | 25 ++- .../ChildExampleViewController.swift | 16 +- .../TableChildExampleViewController.swift | 27 +-- Example/Example/Helpers/DataProvider.swift | 24 +-- Example/Example/Helpers/PostCell.swift | 15 +- .../InstagramExampleViewController.swift | 17 +- .../NavButtonBarExampleViewController.swift | 34 ++-- .../Example/ReloadExampleViewController.swift | 9 +- .../SegmentedExampleViewController.swift | 20 +- .../SpotifyExampleViewController.swift | 23 +-- .../TwitterExampleViewController.swift | 16 +- .../YoutubeExampleViewController.swift | 32 ++- Example/Example/Youtube/YoutubeIconCell.swift | 5 +- Example/ExampleUITests/ExampleUITests.swift | 12 +- Playground.playground/Contents.swift | 2 +- Sources/BarPagerTabStripViewController.swift | 24 +-- Sources/BarView.swift | 24 ++- ...ButtonBarPagerTabStripViewController.swift | 43 ++-- ...ButtonBarPagerTabStripViewController.swift | 132 ++++++------- Sources/ButtonBarView.swift | 73 ++++--- Sources/ButtonBarViewCell.swift | 4 +- Sources/IndicatorInfo.swift | 21 +- Sources/PagerTabStripBehaviour.swift | 13 +- Sources/PagerTabStripError.swift | 4 +- Sources/PagerTabStripViewController.swift | 185 ++++++++---------- ...SegmentedPagerTabStripViewController.swift | 36 ++-- .../TwitterPagerTabStripViewController.swift | 63 +++--- Tests/XLPagerTabStripTests.swift | 10 +- XLPagerTabStrip.xcodeproj/project.pbxproj | 18 ++ 32 files changed, 504 insertions(+), 512 deletions(-) create mode 100644 .swiftlint.yml diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 00000000..c0c6df0b --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,51 @@ +disabled_rules: # rule identifiers to exclude from running +# - colon +# - comma +# - control_statement + - line_length + - function_body_length + - identifier_name + - type_name + - large_tuple +opt_in_rules: # some rules are only opt-in + - empty_count + # Find all the available rules by running: + # swiftlint rules +excluded: # paths to ignore during linting. Takes precedence over `included`. + - Carthage + - Pods + - Source/ExcludedFolder + - Source/ExcludedFile.swift + +# configurable rules can be customized from this configuration file +# binary rules can set their severity level +force_cast: warning # implicitly +force_try: + severity: warning # explicitly +# rules that have both warning and error levels, can set just the warning level +# implicitly +line_length: 200 +# they can set both implicitly with an array +type_body_length: + - 300 # warning + - 400 # error +# or they can set both explicitly +file_length: + warning: 500 + error: 1200 +# naming rules can set warnings/errors for min_length and max_length +# additionally they can set excluded names +type_name: + min_length: 4 # only warning + max_length: # warning and error + warning: 40 + error: 50 + excluded: iPhone # excluded via string +identifier_name: + min_length: # only min_length + error: 4 # only error + excluded: # excluded via string array + - id + - URL + - GlobalAPIKey +reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji) \ No newline at end of file diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift index 0bf0166b..2b1cd0b4 100644 --- a/Example/Example/AppDelegate.swift +++ b/Example/Example/AppDelegate.swift @@ -12,15 +12,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. - + UITabBar.appearance().tintColor = UIColor.init(red: 0.027, green: 0.725, blue: 0.608, alpha: 1) UIApplication.shared.statusBarStyle = .lightContent - - let _ = YoutubeExampleViewController(nibName: nil, bundle: nil) - + + _ = YoutubeExampleViewController(nibName: nil, bundle: nil) + return true } @@ -46,6 +45,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - } - diff --git a/Example/Example/BarExampleViewController.swift b/Example/Example/BarExampleViewController.swift index 0d075963..372a4a2d 100644 --- a/Example/Example/BarExampleViewController.swift +++ b/Example/Example/BarExampleViewController.swift @@ -27,51 +27,50 @@ import XLPagerTabStrip class BarExampleViewController: BarPagerTabStripViewController { var isReload = false - + required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } - + override func viewDidLoad() { - + // set up style before super view did load is executed settings.style.selectedBarBackgroundColor = .orange // - - + super.viewDidLoad() } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { - + let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "Table View") let child_2 = ChildExampleViewController(itemInfo: "View") let child_3 = TableChildExampleViewController(style: .grouped, itemInfo: "Table View 2") let child_4 = ChildExampleViewController(itemInfo: "View 2") - + guard isReload else { return [child_1, child_2, child_3, child_4] } - + var childViewControllers = [child_1, child_2, child_3, child_4] - for (index, _) in childViewControllers.enumerated(){ + for index in childViewControllers.indices { let nElements = childViewControllers.count - index let n = (Int(arc4random()) % nElements) + index - if n != index{ + if n != index { swap(&childViewControllers[index], &childViewControllers[n]) } } let nItems = 1 + (arc4random() % 4) return Array(childViewControllers.prefix(Int(nItems))) } - + override func reloadPagerTabStripView() { isReload = true if arc4random() % 2 == 0 { pagerBehaviour = .progressive(skipIntermediateViewControllers: arc4random() % 2 == 0, elasticIndicatorLimit: arc4random() % 2 == 0 ) - } - else { + } else { pagerBehaviour = .common(skipIntermediateViewControllers: arc4random() % 2 == 0) } super.reloadPagerTabStripView() diff --git a/Example/Example/ButtonBarExampleViewController.swift b/Example/Example/ButtonBarExampleViewController.swift index 90556d75..e60b4a85 100644 --- a/Example/Example/ButtonBarExampleViewController.swift +++ b/Example/Example/ButtonBarExampleViewController.swift @@ -26,18 +26,18 @@ import Foundation import XLPagerTabStrip class ButtonBarExampleViewController: ButtonBarPagerTabStripViewController { - + var isReload = false - + override func viewDidLoad() { super.viewDidLoad() - + buttonBarView.selectedBar.backgroundColor = .orange buttonBarView.backgroundColor = UIColor(red: 7/255, green: 185/255, blue: 155/255, alpha: 1) } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "Table View") let child_2 = ChildExampleViewController(itemInfo: "View") @@ -47,30 +47,29 @@ class ButtonBarExampleViewController: ButtonBarPagerTabStripViewController { let child_6 = ChildExampleViewController(itemInfo: "View 3") let child_7 = TableChildExampleViewController(style: .grouped, itemInfo: "Table View 4") let child_8 = ChildExampleViewController(itemInfo: "View 4") - + guard isReload else { return [child_1, child_2, child_3, child_4, child_5, child_6, child_7, child_8] } - + var childViewControllers = [child_1, child_2, child_3, child_4, child_6, child_7, child_8] - - for (index, _) in childViewControllers.enumerated(){ + + for index in childViewControllers.indices { let nElements = childViewControllers.count - index let n = (Int(arc4random()) % nElements) + index - if n != index{ + if n != index { swap(&childViewControllers[index], &childViewControllers[n]) } } let nItems = 1 + (arc4random() % 8) return Array(childViewControllers.prefix(Int(nItems))) } - + override func reloadPagerTabStripView() { isReload = true if arc4random() % 2 == 0 { pagerBehaviour = .progressive(skipIntermediateViewControllers: arc4random() % 2 == 0, elasticIndicatorLimit: arc4random() % 2 == 0 ) - } - else { + } else { pagerBehaviour = .common(skipIntermediateViewControllers: arc4random() % 2 == 0) } super.reloadPagerTabStripView() diff --git a/Example/Example/ChildControllers/ChildExampleViewController.swift b/Example/Example/ChildControllers/ChildExampleViewController.swift index e1b3fe88..b31f716a 100644 --- a/Example/Example/ChildControllers/ChildExampleViewController.swift +++ b/Example/Example/ChildControllers/ChildExampleViewController.swift @@ -26,9 +26,9 @@ import Foundation import XLPagerTabStrip class ChildExampleViewController: UIViewController, IndicatorInfoProvider { - + var itemInfo: IndicatorInfo = "View" - + init(itemInfo: IndicatorInfo) { self.itemInfo = itemInfo super.init(nibName: nil, bundle: nil) @@ -37,23 +37,23 @@ class ChildExampleViewController: UIViewController, IndicatorInfoProvider { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.text = "XLPagerTabStrip" - + view.addSubview(label) view.backgroundColor = .white - + view.addConstraint(NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: -50)) } - + // MARK: - IndicatorInfoProvider - + func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo { return itemInfo } diff --git a/Example/Example/ChildControllers/TableChildExampleViewController.swift b/Example/Example/ChildControllers/TableChildExampleViewController.swift index d24edeed..35ffd392 100644 --- a/Example/Example/ChildControllers/TableChildExampleViewController.swift +++ b/Example/Example/ChildControllers/TableChildExampleViewController.swift @@ -26,60 +26,61 @@ import Foundation import XLPagerTabStrip class TableChildExampleViewController: UITableViewController, IndicatorInfoProvider { - + let cellIdentifier = "postCell" var blackTheme = false var itemInfo = IndicatorInfo(title: "View") - + init(style: UITableViewStyle, itemInfo: IndicatorInfo) { self.itemInfo = itemInfo super.init(style: style) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(UINib(nibName: "PostCell", bundle: Bundle.main), forCellReuseIdentifier: cellIdentifier) - tableView.estimatedRowHeight = 60.0; + tableView.estimatedRowHeight = 60.0 tableView.rowHeight = UITableViewAutomaticDimension tableView.allowsSelection = false if blackTheme { tableView.backgroundColor = UIColor(red: 15/255.0, green: 16/255.0, blue: 16/255.0, alpha: 1.0) } } - + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) tableView.reloadData() } - + // MARK: - UITableViewDataSource - + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return DataProvider.sharedInstance.postsData.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! PostCell - let data = DataProvider.sharedInstance.postsData.object(at: indexPath.row) as! - NSDictionary + guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PostCell, + let data = DataProvider.sharedInstance.postsData.object(at: indexPath.row) as? NSDictionary else { return PostCell() } + cell.configureWithData(data) if blackTheme { cell.changeStylToBlack() } return cell } - + // MARK: - IndicatorInfoProvider func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo { return itemInfo } + } diff --git a/Example/Example/Helpers/DataProvider.swift b/Example/Example/Helpers/DataProvider.swift index 94b77915..d1b635e9 100644 --- a/Example/Example/Helpers/DataProvider.swift +++ b/Example/Example/Helpers/DataProvider.swift @@ -27,33 +27,27 @@ import UIKit class DataProvider { static let sharedInstance = DataProvider() - + lazy var postsData: NSArray = { let jsonStr = "[{\"post\":{\"id\":113,\"text\":\"We're getting fifty percent of the t-shirt sales\",\"created_at\":\"2014-04-17T00:45:40.556Z\",\"user\":{\"id\":9,\"name\":\"Lisa Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Lisa_Simpsons.png\"}}},{\"post\":{\"id\":66,\"text\":\"Eep!\",\"created_at\":\"2014-04-09T21:29:59.982Z\",\"user\":{\"id\":7,\"name\":\"Bart Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Bart_Simpsons.png\"}}},{\"post\":{\"id\":42,\"text\":\"I'm not thinking straight, why did I have that wine cooler last month?\",\"created_at\":\"2014-04-09T17:58:41.704Z\",\"user\":{\"id\":5,\"name\":\"Ned Flanders\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Ned_Flanders.png\"}}},{\"post\":{\"id\":84,\"text\":\"Son, when you participate in sporting events, it's not whether you win or lose: it's how drunk you get.\",\"created_at\":\"2014-04-03T20:21:32.119Z\",\"user\":{\"id\":8,\"name\":\"Homer Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Homer_Simpsons.png\"}}},{\"post\":{\"id\":75,\"text\":\"I'm normally not a praying man, but if you're up there, please save me Superman.\",\"created_at\":\"2014-04-03T02:04:43.053Z\",\"user\":{\"id\":8,\"name\":\"Homer Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Homer_Simpsons.png\"}}},{\"post\":{\"id\":26,\"text\":\"Homer, please get rid of that pig.\",\"created_at\":\"2014-04-02T03:48:56.381Z\",\"user\":{\"id\":3,\"name\":\"Marge Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Marge_Simpsons.png\"}}},{\"post\":{\"id\":40,\"text\":\"You sold weapon-grade plutoneum to the Iraqies without a mark up.\",\"created_at\":\"2014-03-28T05:23:24.657Z\",\"user\":{\"id\":4,\"name\":\"Montgomery Burns\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Montgomery_Burns.png\"}}},{\"post\":{\"id\":28,\"text\":\"Homer, don't say that. The way I see it, if you raised three children who can knock out and hog tie a perfect stranger you must be doing something right.\",\"created_at\":\"2014-03-22T14:24:22.408Z\",\"user\":{\"id\":3,\"name\":\"Marge Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Marge_Simpsons.png\"}}},{\"post\":{\"id\":48,\"text\":\"Hi-dilly-ho, neighborinos!\",\"created_at\":\"2014-03-21T08:39:20.764Z\",\"user\":{\"id\":5,\"name\":\"Ned Flanders\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Ned_Flanders.png\"}}},{\"post\":{\"id\":78,\"text\":\"Maybe, just once, someone will call me 'Sir' without adding, 'You're making a scene.'\",\"created_at\":\"2014-03-20T02:44:28.075Z\",\"user\":{\"id\":8,\"name\":\"Homer Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Homer_Simpsons.png\"}}},{\"post\":{\"id\":33,\"text\":\"This is the type of trickery I pay you for.\",\"created_at\":\"2014-03-18T08:25:14.507Z\",\"user\":{\"id\":4,\"name\":\"Montgomery Burns\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Montgomery_Burns.png\"}}},{\"post\":{\"id\":72,\"text\":\"Oh, so they have internet on computers now!\",\"created_at\":\"2014-03-03T19:02:56.032Z\",\"user\":{\"id\":8,\"name\":\"Homer Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Homer_Simpsons.png\"}}},{\"post\":{\"id\":1,\"text\":\"You know, I do! I mean, there comes a time in a man's life when he asks himself, 'who will float my corpse down the Ganges?'\",\"created_at\":\"2014-02-24T14:09:00.912Z\",\"user\":{\"id\":1,\"name\":\"Apu Nahasapeemapetilon\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Apu_Nahasapeemapetilon.png\"}}},{\"post\":{\"id\":62,\"text\":\"Ay Caramba!\",\"created_at\":\"2014-02-18T16:38:37.958Z\",\"user\":{\"id\":7,\"name\":\"Bart Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Bart_Simpsons.png\"}}},{\"post\":{\"id\":19,\"text\":\"Throughout the ages, the finger painter, the Play-Doh sculptor, the Lincoln Logger, stood alone against the daycare teacher of her time. She did not live to earn aproval stickers, she lived for herself, that she might achieve things that are the glory of all humanity. These are my terms. I do not care to play by any others. And now, if the jury will allow me, it's naptime.\",\"created_at\":\"2014-02-16T22:11:33.236Z\",\"user\":{\"id\":2,\"name\":\"Maggie Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Maggie_Simpsons.png\"}}},{\"post\":{\"id\":76,\"text\":\"Son, if you really want something in this life, you have to work for it. Now quiet! They're about to announce the lottery numbers.\",\"created_at\":\"2014-02-16T19:09:55.062Z\",\"user\":{\"id\":8,\"name\":\"Homer Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Homer_Simpsons.png\"}}},{\"post\":{\"id\":22,\"text\":\"Somebody throw the goddamn bomb!\",\"created_at\":\"2014-02-16T13:50:25.313Z\",\"user\":{\"id\":3,\"name\":\"Marge Simpsons\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Marge_Simpsons.png\"}}},{\"post\":{\"id\":36,\"text\":\"Oh, so mother nature needs a favor? Well, maybe she should have thought of that when she was besetting us with droughts and floods and poison monkeys.\",\"created_at\":\"2014-02-13T06:51:57.549Z\",\"user\":{\"id\":4,\"name\":\"Montgomery Burns\",\"imageURL\":\"http://obscure-refuge-3149.herokuapp.com/images/Montgomery_Burns.png\"}}}]" let jsonData = jsonStr.data(using: String.Encoding.utf8) - return try! JSONSerialization.jsonObject(with: jsonData!, options: []) as! NSArray + let res = try! JSONSerialization.jsonObject(with: jsonData!, options: []) // swiftlint:disable:this force_try + return res as! NSArray // swiftlint:disable:this force_cast }() } class NavController: UINavigationController { - - - override var preferredStatusBarStyle : UIStatusBarStyle { + + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } - + } +class TabBarController: UITabBarController { -class TabBarController : UITabBarController { - - override var preferredStatusBarStyle : UIStatusBarStyle { + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } - -} - - - - +} diff --git a/Example/Example/Helpers/PostCell.swift b/Example/Example/Helpers/PostCell.swift index 0a44630c..b9c26721 100644 --- a/Example/Example/Helpers/PostCell.swift +++ b/Example/Example/Helpers/PostCell.swift @@ -25,28 +25,25 @@ import UIKit class PostCell: UITableViewCell { - - + @IBOutlet weak var userImage: UIImageView! @IBOutlet weak var postName: UILabel! @IBOutlet weak var postText: UILabel! - + override func awakeFromNib() { super.awakeFromNib() userImage.layer.cornerRadius = 10.0 } - - - func configureWithData(_ data: NSDictionary){ + + func configureWithData(_ data: NSDictionary) { if let post = data["post"] as? NSDictionary, let user = post["user"] as? NSDictionary { postName.text = user["name"] as? String postText.text = post["text"] as? String userImage.image = UIImage(named: postName.text!.replacingOccurrences(of: " ", with: "_")) } } - - - func changeStylToBlack(){ + + func changeStylToBlack() { userImage?.layer.cornerRadius = 30.0 postText.text = nil postName.font = UIFont(name: "HelveticaNeue-Light", size:18) ?? .systemFont(ofSize: 18) diff --git a/Example/Example/Instagram/InstagramExampleViewController.swift b/Example/Example/Instagram/InstagramExampleViewController.swift index ce9a4180..392cae15 100644 --- a/Example/Example/Instagram/InstagramExampleViewController.swift +++ b/Example/Example/Instagram/InstagramExampleViewController.swift @@ -26,10 +26,10 @@ import Foundation import XLPagerTabStrip class InstagramExampleViewController: ButtonBarPagerTabStripViewController { - + @IBOutlet weak var shadowView: UIView! let blueInstagramColor = UIColor(red: 37/255.0, green: 111/255.0, blue: 206/255.0, alpha: 1.0) - + override func viewDidLoad() { // change selected bar color settings.style.buttonBarBackgroundColor = .white @@ -42,7 +42,7 @@ class InstagramExampleViewController: ButtonBarPagerTabStripViewController { settings.style.buttonBarItemsShouldFillAvailableWidth = true settings.style.buttonBarLeftContentInset = 0 settings.style.buttonBarRightContentInset = 0 - + changeCurrentIndexProgressive = { [weak self] (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in guard changeCurrentIndex == true else { return } oldCell?.label.textColor = .black @@ -50,9 +50,9 @@ class InstagramExampleViewController: ButtonBarPagerTabStripViewController { } super.viewDidLoad() } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "FOLLOWING") let child_2 = ChildExampleViewController(itemInfo: "YOU") @@ -60,13 +60,8 @@ class InstagramExampleViewController: ButtonBarPagerTabStripViewController { } // MARK: - Custom Action - + @IBAction func closeAction(_ sender: UIButton) { dismiss(animated: true, completion: nil) } } - - - - - diff --git a/Example/Example/NavButtonBarExampleViewController.swift b/Example/Example/NavButtonBarExampleViewController.swift index f7d1fdc3..8510510d 100644 --- a/Example/Example/NavButtonBarExampleViewController.swift +++ b/Example/Example/NavButtonBarExampleViewController.swift @@ -27,38 +27,37 @@ import XLPagerTabStrip class NavButtonBarExampleViewController: ButtonBarPagerTabStripViewController { var isReload = false - + override func viewDidLoad() { // set up style before super view did load is executed settings.style.buttonBarBackgroundColor = .clear settings.style.selectedBarBackgroundColor = .orange //- super.viewDidLoad() - + buttonBarView.removeFromSuperview() navigationController?.navigationBar.addSubview(buttonBarView) - + changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in guard changeCurrentIndex == true else { return } - + oldCell?.label.textColor = UIColor(white: 1, alpha: 0.6) newCell?.label.textColor = .white - + if animated { UIView.animate(withDuration: 0.1, animations: { () -> Void in newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) }) - } - else { + } else { newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) } } } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "Table View") let child_2 = ChildExampleViewController(itemInfo: "View") @@ -68,35 +67,34 @@ class NavButtonBarExampleViewController: ButtonBarPagerTabStripViewController { let child_6 = ChildExampleViewController(itemInfo: "View 2") let child_7 = TableChildExampleViewController(style: .grouped, itemInfo: "Table View 4") let child_8 = ChildExampleViewController(itemInfo: "View 3") - + guard isReload else { return [child_1, child_2, child_3, child_4, child_5, child_6, child_7, child_8] } - + var childViewControllers = [child_1, child_2, child_3, child_4, child_6, child_7, child_8] - - for (index, _) in childViewControllers.enumerated(){ + + for index in childViewControllers.indices { let nElements = childViewControllers.count - index let n = (Int(arc4random()) % nElements) + index - if n != index{ + if n != index { swap(&childViewControllers[index], &childViewControllers[n]) } } let nItems = 1 + (arc4random() % 8) return Array(childViewControllers.prefix(Int(nItems))) } - + override func reloadPagerTabStripView() { isReload = true if arc4random() % 2 == 0 { pagerBehaviour = .progressive(skipIntermediateViewControllers: arc4random() % 2 == 0, elasticIndicatorLimit: arc4random() % 2 == 0 ) - } - else { + } else { pagerBehaviour = .common(skipIntermediateViewControllers: arc4random() % 2 == 0) } super.reloadPagerTabStripView() } - + override func configureCell(_ cell: ButtonBarViewCell, indicatorInfo: IndicatorInfo) { super.configureCell(cell, indicatorInfo: indicatorInfo) cell.backgroundColor = .clear diff --git a/Example/Example/ReloadExampleViewController.swift b/Example/Example/ReloadExampleViewController.swift index bc5a4113..51cdfc3c 100644 --- a/Example/Example/ReloadExampleViewController.swift +++ b/Example/Example/ReloadExampleViewController.swift @@ -44,12 +44,12 @@ class ReloadExampleViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - if let _ = navigationController { + if navigationController != nil { navigationItem.titleView = bigLabel bigLabel.sizeToFit() } - if let pagerViewController = childViewControllers.filter( { $0 is PagerTabStripViewController } ).first as? PagerTabStripViewController { + if let pagerViewController = childViewControllers.first as? PagerTabStripViewController { updateTitle(of: pagerViewController) } } @@ -61,11 +61,10 @@ class ReloadExampleViewController: UIViewController { } child.reloadPagerTabStripView() updateTitle(of: child) - break; + break } } - @IBAction func closeTapped(_ sender: UIButton) { dismiss(animated: true, completion: nil) } @@ -81,7 +80,7 @@ class ReloadExampleViewController: UIViewController { navigationItem.titleView?.sizeToFit() } - override var preferredStatusBarStyle : UIStatusBarStyle { + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } } diff --git a/Example/Example/SegmentedExampleViewController.swift b/Example/Example/SegmentedExampleViewController.swift index a9535110..32590219 100644 --- a/Example/Example/SegmentedExampleViewController.swift +++ b/Example/Example/SegmentedExampleViewController.swift @@ -26,41 +26,41 @@ import Foundation import XLPagerTabStrip class SegmentedExampleViewController: SegmentedPagerTabStripViewController { - + var isReload = false - + required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) // change segmented style settings.style.segmentedControlColor = .white } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "Table View") let child_2 = ChildExampleViewController(itemInfo: "View") let child_3 = TableChildExampleViewController(style: .grouped, itemInfo: "Table View 2") let child_4 = ChildExampleViewController(itemInfo: "View 2") - + guard isReload else { return [child_1, child_2, child_3, child_4] } - + var childViewControllers = [child_1, child_2, child_3, child_4] let count = childViewControllers.count - - for (index, _) in childViewControllers.enumerated(){ + + for index in childViewControllers.indices { let nElements = count - index let n = (Int(arc4random()) % nElements) + index - if n != index{ + if n != index { swap(&childViewControllers[index], &childViewControllers[n]) } } let nItems = 1 + (arc4random() % 4) return Array(childViewControllers.prefix(Int(nItems))) } - + @IBAction func reloadTapped(_ sender: UIBarButtonItem) { isReload = true pagerBehaviour = .common(skipIntermediateViewControllers: arc4random() % 2 == 0) diff --git a/Example/Example/Spotify/SpotifyExampleViewController.swift b/Example/Example/Spotify/SpotifyExampleViewController.swift index a76256c0..4fa26a5d 100644 --- a/Example/Example/Spotify/SpotifyExampleViewController.swift +++ b/Example/Example/Spotify/SpotifyExampleViewController.swift @@ -26,12 +26,12 @@ import Foundation import XLPagerTabStrip class SpotifyExampleViewController: ButtonBarPagerTabStripViewController { - + @IBOutlet weak var shadowView: UIView! - + let graySpotifyColor = UIColor(red: 21/255.0, green: 21/255.0, blue: 24/255.0, alpha: 1.0) let darkGraySpotifyColor = UIColor(red: 19/255.0, green: 20/255.0, blue: 20/255.0, alpha: 1.0) - + override func viewDidLoad() { // change selected bar color settings.style.buttonBarBackgroundColor = graySpotifyColor @@ -42,10 +42,10 @@ class SpotifyExampleViewController: ButtonBarPagerTabStripViewController { settings.style.buttonBarMinimumLineSpacing = 0 settings.style.buttonBarItemTitleColor = .black settings.style.buttonBarItemsShouldFillAvailableWidth = true - + settings.style.buttonBarLeftContentInset = 20 settings.style.buttonBarRightContentInset = 20 - + changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in guard changeCurrentIndex == true else { return } oldCell?.label.textColor = UIColor(red: 138/255.0, green: 138/255.0, blue: 144/255.0, alpha: 1.0) @@ -53,9 +53,9 @@ class SpotifyExampleViewController: ButtonBarPagerTabStripViewController { } super.viewDidLoad() } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: IndicatorInfo(title: "FRIENDS")) child_1.blackTheme = true @@ -63,15 +63,10 @@ class SpotifyExampleViewController: ButtonBarPagerTabStripViewController { child_2.blackTheme = true return [child_1, child_2] } - + // MARK: - Actions - + @IBAction func closeAction(_ sender: UIButton) { dismiss(animated: true, completion: nil) } } - - - - - diff --git a/Example/Example/TwitterExampleViewController.swift b/Example/Example/TwitterExampleViewController.swift index 664eb283..f0e5484e 100644 --- a/Example/Example/TwitterExampleViewController.swift +++ b/Example/Example/TwitterExampleViewController.swift @@ -27,9 +27,9 @@ import XLPagerTabStrip class TwitterExampleViewController: TwitterPagerTabStripViewController { var isReload = false - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { - + let child_1 = TableChildExampleViewController(style: .plain, itemInfo: "TableView") let child_2 = ChildExampleViewController(itemInfo: "View") let child_3 = TableChildExampleViewController(style: .grouped, itemInfo: "TableView 2") @@ -38,24 +38,24 @@ class TwitterExampleViewController: TwitterPagerTabStripViewController { let child_6 = ChildExampleViewController(itemInfo: "View 3") let child_7 = TableChildExampleViewController(style: .grouped, itemInfo: "TableView 4") let child_8 = ChildExampleViewController(itemInfo: "View 4") - + guard isReload else { return [child_1, child_2, child_3, child_4, child_5, child_6, child_7, child_8] } - + var childViewControllers = [child_1, child_2, child_3, child_4, child_6, child_7, child_8] - - for (index, _) in childViewControllers.enumerated(){ + + for index in childViewControllers.indices { let nElements = childViewControllers.count - index let n = (Int(arc4random()) % nElements) + index - if n != index{ + if n != index { swap(&childViewControllers[index], &childViewControllers[n]) } } let nItems = 1 + (arc4random() % 8) return Array(childViewControllers.prefix(Int(nItems))) } - + @IBAction func reloadTapped(_ sender: AnyObject) { isReload = true reloadPagerTabStripView() diff --git a/Example/Example/Youtube/YoutubeExampleViewController.swift b/Example/Example/Youtube/YoutubeExampleViewController.swift index 903e1eea..f22e9ea9 100644 --- a/Example/Example/Youtube/YoutubeExampleViewController.swift +++ b/Example/Example/Youtube/YoutubeExampleViewController.swift @@ -30,19 +30,18 @@ class YoutubeExampleViewController: BaseButtonBarPagerTabStripViewController CGFloat in + + buttonBarItemSpec = ButtonBarItemSpec.nibFile(nibName: "YoutubeIconCell", bundle: Bundle(for: YoutubeIconCell.self), width: { _ in return 55.0 }) } - + override func viewDidLoad() { // change selected bar color settings.style.buttonBarBackgroundColor = redColor @@ -54,53 +53,44 @@ class YoutubeExampleViewController: BaseButtonBarPagerTabStripViewController Void in guard changeCurrentIndex == true else { return } oldCell?.iconImage.tintColor = self?.unselectedIconColor newCell?.iconImage.tintColor = .white - } super.viewDidLoad() navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) } - + // MARK: - PagerTabStripDataSource - + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: IndicatorInfo(title: " HOME", image: UIImage(named: "home"))) let child_2 = TableChildExampleViewController(style: .plain, itemInfo: IndicatorInfo(title: " TRENDING", image: UIImage(named: "trending"))) let child_3 = ChildExampleViewController(itemInfo: IndicatorInfo(title: " ACCOUNT", image: UIImage(named: "profile"))) return [child_1, child_2, child_3] } - - + override func configure(cell: YoutubeIconCell, for indicatorInfo: IndicatorInfo) { cell.iconImage.image = indicatorInfo.image?.withRenderingMode(.alwaysTemplate) } - + override func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) { super.updateIndicator(for: viewController, fromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: progressPercentage, indexWasChanged: indexWasChanged) if indexWasChanged && toIndex > -1 && toIndex < viewControllers.count { - let child = viewControllers[toIndex] as! IndicatorInfoProvider + let child = viewControllers[toIndex] as! IndicatorInfoProvider // swiftlint:disable:this force_cast UIView.performWithoutAnimation({ [weak self] () -> Void in guard let me = self else { return } me.navigationItem.leftBarButtonItem?.title = child.indicatorInfo(for: me).title }) } } - + // MARK: - Actions @IBAction func closeAction(_ sender: UIButton) { dismiss(animated: true, completion: nil) } } - - - - - diff --git a/Example/Example/Youtube/YoutubeIconCell.swift b/Example/Example/Youtube/YoutubeIconCell.swift index 265b4136..5716b9dd 100644 --- a/Example/Example/Youtube/YoutubeIconCell.swift +++ b/Example/Example/Youtube/YoutubeIconCell.swift @@ -25,9 +25,8 @@ import Foundation import UIKit +class YoutubeIconCell: UICollectionViewCell { -class YoutubeIconCell : UICollectionViewCell { - @IBOutlet weak var iconImage: UIImageView! - + } diff --git a/Example/ExampleUITests/ExampleUITests.swift b/Example/ExampleUITests/ExampleUITests.swift index bc1ad44c..85e42f87 100644 --- a/Example/ExampleUITests/ExampleUITests.swift +++ b/Example/ExampleUITests/ExampleUITests.swift @@ -8,12 +8,12 @@ import XCTest class ExampleUITests: XCTestCase { - + override func setUp() { super.setUp() - + // Put setup code here. This method is called before the invocation of each test method in the class. - + // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. @@ -21,15 +21,15 @@ class ExampleUITests: XCTestCase { // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testExample() { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } - + } diff --git a/Playground.playground/Contents.swift b/Playground.playground/Contents.swift index 633b8b8d..39c45e89 100644 --- a/Playground.playground/Contents.swift +++ b/Playground.playground/Contents.swift @@ -10,4 +10,4 @@ import UIKit import XLPagerTabStrip -var str = "Hello, playground" +var helloWorld = "Hello, playground" diff --git a/Sources/BarPagerTabStripViewController.swift b/Sources/BarPagerTabStripViewController.swift index be244afe..e231268a 100644 --- a/Sources/BarPagerTabStripViewController.swift +++ b/Sources/BarPagerTabStripViewController.swift @@ -26,34 +26,34 @@ import Foundation import UIKit public struct BarPagerTabStripSettings { - + public struct Style { public var barBackgroundColor: UIColor? public var selectedBarBackgroundColor: UIColor? public var barHeight: CGFloat = 5 // barHeight is ony set up when the bar is created programatically and not using storyboards or xib files. } - + public var style = Style() } open class BarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate { - + public var settings = BarPagerTabStripSettings() - + @IBOutlet weak public var barView: BarView! - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) delegate = self datasource = self } - + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) delegate = self datasource = self } - + open override func viewDidLoad() { super.viewDidLoad() barView = barView ?? { @@ -63,11 +63,11 @@ open class BarPagerTabStripViewController: PagerTabStripViewController, PagerTab barView.selectedBar.backgroundColor = .white return barView }() - + barView.backgroundColor = settings.style.barBackgroundColor ?? barView.backgroundColor barView.selectedBar.backgroundColor = settings.style.selectedBarBackgroundColor ?? barView.selectedBar.backgroundColor } - + open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if barView.superview == nil { @@ -76,15 +76,15 @@ open class BarPagerTabStripViewController: PagerTabStripViewController, PagerTab barView.optionsCount = viewControllers.count barView.moveTo(index: currentIndex, animated: false) } - + open override func reloadPagerTabStripView() { super.reloadPagerTabStripView() barView.optionsCount = viewControllers.count - if isViewLoaded{ + if isViewLoaded { barView.moveTo(index: currentIndex, animated: false) } } - + // MARK: - PagerTabStripDelegate open func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) { diff --git a/Sources/BarView.swift b/Sources/BarView.swift index aa4dac21..1183524d 100644 --- a/Sources/BarView.swift +++ b/Sources/BarView.swift @@ -25,12 +25,12 @@ import Foundation open class BarView: UIView { - + open lazy var selectedBar: UIView = { [unowned self] in let selectedBar = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)) return selectedBar }() - + var optionsCount = 1 { willSet(newOptionsCount) { if newOptionsCount <= selectedIndex { @@ -39,20 +39,19 @@ open class BarView: UIView { } } var selectedIndex = 0 - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) addSubview(selectedBar) } - + override init(frame: CGRect) { super.init(frame: frame) addSubview(selectedBar) } - - + // MARK: - Helpers - + private func updateSelectedBarPosition(with animation: Bool) { var frame = selectedBar.frame frame.size.width = self.frame.size.width / CGFloat(optionsCount) @@ -61,20 +60,19 @@ open class BarView: UIView { UIView.animate(withDuration: 0.3, animations: { [weak self] in self?.selectedBar.frame = frame }) - } - else{ + } else { selectedBar.frame = frame } } - + open func moveTo(index: Int, animated: Bool) { selectedIndex = index updateSelectedBarPosition(with: animated) } - + open func move(fromIndex: Int, toIndex: Int, progressPercentage: CGFloat) { selectedIndex = (progressPercentage > 0.5) ? toIndex : fromIndex - + var newFrame = selectedBar.frame newFrame.size.width = frame.size.width / CGFloat(optionsCount) var fromFrame = newFrame @@ -85,7 +83,7 @@ open class BarView: UIView { targetFrame.origin.x += (toFrame.origin.x - targetFrame.origin.x) * CGFloat(progressPercentage) selectedBar.frame = targetFrame } - + open override func layoutSubviews() { super.layoutSubviews() updateSelectedBarPosition(with: false) diff --git a/Sources/BaseButtonBarPagerTabStripViewController.swift b/Sources/BaseButtonBarPagerTabStripViewController.swift index ec083bc2..a069b98f 100644 --- a/Sources/BaseButtonBarPagerTabStripViewController.swift +++ b/Sources/BaseButtonBarPagerTabStripViewController.swift @@ -24,14 +24,13 @@ import Foundation -open class BaseButtonBarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate, UICollectionViewDelegate, UICollectionViewDataSource { +open class BaseButtonBarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate, UICollectionViewDelegate, UICollectionViewDataSource { public var settings = ButtonBarPagerTabStripSettings() public var buttonBarItemSpec: ButtonBarItemSpec! public var changeCurrentIndex: ((_ oldCell: ButtonBarCellType?, _ newCell: ButtonBarCellType?, _ animated: Bool) -> Void)? public var changeCurrentIndexProgressive: ((_ oldCell: ButtonBarCellType?, _ newCell: ButtonBarCellType?, _ progressPercentage: CGFloat, _ changeCurrentIndex: Bool, _ animated: Bool) -> Void)? - @IBOutlet public weak var buttonBarView: ButtonBarView! lazy private var cachedCellWidths: [CGFloat]? = { [unowned self] in @@ -55,7 +54,7 @@ open class BaseButtonBarPagerTabStripViewController suggestedStretchedCellWidth { - totalWidthOfLargeCells += minimumCellWidthValue - numberOfLargeCells += 1 - } + for minimumCellWidthValue in minimumCellWidths where minimumCellWidthValue > suggestedStretchedCellWidth { + totalWidthOfLargeCells += minimumCellWidthValue + numberOfLargeCells += 1 } guard numberOfLargeCells > previousNumberOfLargeCells else { return suggestedStretchedCellWidth } - let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout + let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout // swiftlint:disable:this force_cast let collectionViewAvailiableWidth = buttonBarView.frame.size.width - flowLayout.sectionInset.left - flowLayout.sectionInset.right let numberOfCells = minimumCellWidths.count let cellSpacingTotal = CGFloat(numberOfCells - 1) * flowLayout.minimumLineSpacing @@ -216,8 +213,7 @@ open class BaseButtonBarPagerTabStripViewController [CGFloat] { - let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout + let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout // swiftlint:disable:this force_cast let numberOfCells = viewControllers.count var minimumCellWidths = [CGFloat]() var collectionViewContentWidth: CGFloat = 0 for viewController in viewControllers { - let childController = viewController as! IndicatorInfoProvider + let childController = viewController as! IndicatorInfoProvider // swiftlint:disable:this force_cast let indicatorInfo = childController.indicatorInfo(for: self) switch buttonBarItemSpec! { case .cellClass(let widthCallback): @@ -296,8 +291,7 @@ open class BaseButtonBarPagerTabStripViewController { public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { @@ -327,8 +320,8 @@ open class ExampleBaseButtonBarPagerTabStripViewController: BaseButtonBarPagerTa initialize() } - open func initialize(){ - buttonBarItemSpec = .nibFile(nibName: "ButtonCell", bundle: Bundle(for: ButtonBarViewCell.self), width:{ [weak self] (childItemInfo) -> CGFloat in + open func initialize() { + buttonBarItemSpec = .nibFile(nibName: "ButtonCell", bundle: Bundle(for: ButtonBarViewCell.self), width: { [weak self] (childItemInfo) -> CGFloat in let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.font = self?.settings.style.buttonBarItemFont ?? label.font @@ -338,7 +331,7 @@ open class ExampleBaseButtonBarPagerTabStripViewController: BaseButtonBarPagerTa }) } - open override func configure(cell: ButtonBarViewCell, for indicatorInfo: IndicatorInfo){ + open override func configure(cell: ButtonBarViewCell, for indicatorInfo: IndicatorInfo) { cell.label.text = indicatorInfo.title if let image = indicatorInfo.image { cell.imageView.image = image diff --git a/Sources/ButtonBarPagerTabStripViewController.swift b/Sources/ButtonBarPagerTabStripViewController.swift index 790c7ee7..8f29bcd8 100644 --- a/Sources/ButtonBarPagerTabStripViewController.swift +++ b/Sources/ButtonBarPagerTabStripViewController.swift @@ -25,10 +25,10 @@ import Foundation public enum ButtonBarItemSpec { - + case nibFile(nibName: String, bundle: Bundle?, width:((IndicatorInfo)-> CGFloat)) case cellClass(width:((IndicatorInfo)-> CGFloat)) - + public var weight: ((IndicatorInfo) -> CGFloat) { switch self { case .cellClass(let widthCallback): @@ -40,7 +40,7 @@ public enum ButtonBarItemSpec { } public struct ButtonBarPagerTabStripSettings { - + public struct Style { public var buttonBarBackgroundColor: UIColor? public var buttonBarMinimumInteritemSpacing: CGFloat? @@ -51,7 +51,7 @@ public struct ButtonBarPagerTabStripSettings { public var selectedBarBackgroundColor = UIColor.black public var selectedBarHeight: CGFloat = 5 public var selectedBarVerticalAlignment: SelectedBarVerticalAlignment = .bottom - + public var buttonBarItemBackgroundColor: UIColor? public var buttonBarItemFont = UIFont.systemFont(ofSize: 18) public var buttonBarItemLeftRightMargin: CGFloat = 8 @@ -68,25 +68,25 @@ public struct ButtonBarPagerTabStripSettings { // only used if button bar is created programaticaly and not using storyboards or nib files public var buttonBarHeight: CGFloat? } - + public var style = Style() } open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate, UICollectionViewDelegate, UICollectionViewDataSource { - + public var settings = ButtonBarPagerTabStripSettings() - + public var buttonBarItemSpec: ButtonBarItemSpec! - + public var changeCurrentIndex: ((_ oldCell: ButtonBarViewCell?, _ newCell: ButtonBarViewCell?, _ animated: Bool) -> Void)? public var changeCurrentIndexProgressive: ((_ oldCell: ButtonBarViewCell?, _ newCell: ButtonBarViewCell?, _ progressPercentage: CGFloat, _ changeCurrentIndex: Bool, _ animated: Bool) -> Void)? - + @IBOutlet public weak var buttonBarView: ButtonBarView! - + lazy private var cachedCellWidths: [CGFloat]? = { [unowned self] in return self.calculateWidths() }() - + override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) delegate = self @@ -98,10 +98,10 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa delegate = self datasource = self } - + open override func viewDidLoad() { super.viewDidLoad() - buttonBarItemSpec = .nibFile(nibName: "ButtonCell", bundle: Bundle(for: ButtonBarViewCell.self), width:{ [weak self] (childItemInfo) -> CGFloat in + buttonBarItemSpec = .nibFile(nibName: "ButtonCell", bundle: Bundle(for: ButtonBarViewCell.self), width: { [weak self] (childItemInfo) -> CGFloat in let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.font = self?.settings.style.buttonBarItemFont @@ -109,8 +109,7 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa let labelSize = label.intrinsicContentSize return labelSize.width + (self?.settings.style.buttonBarItemLeftRightMargin ?? 8) * 2 }) - - + let buttonBarViewAux = buttonBarView ?? { let flowLayout = UICollectionViewFlowLayout() flowLayout.scrollDirection = .horizontal @@ -126,7 +125,7 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa return buttonBar }() buttonBarView = buttonBarViewAux - + if buttonBarView.superview == nil { view.addSubview(buttonBarView) } @@ -137,20 +136,20 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa buttonBarView.dataSource = self } buttonBarView.scrollsToTop = false - let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout + let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout // swiftlint:disable:this force_cast flowLayout.scrollDirection = .horizontal flowLayout.minimumInteritemSpacing = settings.style.buttonBarMinimumInteritemSpacing ?? flowLayout.minimumInteritemSpacing flowLayout.minimumLineSpacing = settings.style.buttonBarMinimumLineSpacing ?? flowLayout.minimumLineSpacing let sectionInset = flowLayout.sectionInset - flowLayout.sectionInset = UIEdgeInsetsMake(sectionInset.top, settings.style.buttonBarLeftContentInset ?? sectionInset.left, sectionInset.bottom, settings.style.buttonBarRightContentInset ?? sectionInset.right) + flowLayout.sectionInset = UIEdgeInsets(top: sectionInset.top, left: settings.style.buttonBarLeftContentInset ?? sectionInset.left, bottom: sectionInset.bottom, right: settings.style.buttonBarRightContentInset ?? sectionInset.right) buttonBarView.showsHorizontalScrollIndicator = false buttonBarView.backgroundColor = settings.style.buttonBarBackgroundColor ?? buttonBarView.backgroundColor buttonBarView.selectedBar.backgroundColor = settings.style.selectedBarBackgroundColor - + buttonBarView.selectedBarHeight = settings.style.selectedBarHeight buttonBarView.selectedBarVerticalAlignment = settings.style.selectedBarVerticalAlignment - + // register button bar item cell switch buttonBarItemSpec! { case .nibFile(let nibName, let bundle, _): @@ -160,17 +159,17 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa } //- } - + open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) buttonBarView.layoutIfNeeded() } - + open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - + guard isViewAppearing || isViewRotating else { return } - + // Force the UICollectionViewFlowLayout to get laid out again with the new size if // a) The view is appearing. This ensures that // collectionView:layout:sizeForItemAtIndexPath: is called for a second time @@ -188,9 +187,9 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa // tab/cell may end up either skewed or off screen after a rotation otherwise) buttonBarView.moveTo(index: currentIndex, animated: false, swipeDirection: .none, pagerScroll: .scrollOnlyIfOutOfScreen) } - + // MARK: - Public Methods - + open override func reloadPagerTabStripView() { super.reloadPagerTabStripView() guard isViewLoaded else { return } @@ -198,33 +197,33 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa cachedCellWidths = calculateWidths() buttonBarView.moveTo(index: currentIndex, animated: false, swipeDirection: .none, pagerScroll: .yes) } - + open func calculateStretchedCellWidths(_ minimumCellWidths: [CGFloat], suggestedStretchedCellWidth: CGFloat, previousNumberOfLargeCells: Int) -> CGFloat { var numberOfLargeCells = 0 var totalWidthOfLargeCells: CGFloat = 0 - + for minimumCellWidthValue in minimumCellWidths where minimumCellWidthValue > suggestedStretchedCellWidth { totalWidthOfLargeCells += minimumCellWidthValue numberOfLargeCells += 1 } - + guard numberOfLargeCells > previousNumberOfLargeCells else { return suggestedStretchedCellWidth } - - let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout + + let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout // swiftlint:disable:this force_cast let collectionViewAvailiableWidth = buttonBarView.frame.size.width - flowLayout.sectionInset.left - flowLayout.sectionInset.right let numberOfCells = minimumCellWidths.count let cellSpacingTotal = CGFloat(numberOfCells - 1) * flowLayout.minimumLineSpacing - + let numberOfSmallCells = numberOfCells - numberOfLargeCells let newSuggestedStretchedCellWidth = (collectionViewAvailiableWidth - totalWidthOfLargeCells - cellSpacingTotal) / CGFloat(numberOfSmallCells) - + return calculateStretchedCellWidths(minimumCellWidths, suggestedStretchedCellWidth: newSuggestedStretchedCellWidth, previousNumberOfLargeCells: numberOfLargeCells) } open func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int) { guard shouldUpdateButtonBarView else { return } buttonBarView.moveTo(index: toIndex, animated: false, swipeDirection: toIndex < fromIndex ? .right : .left, pagerScroll: .yes) - + if let changeCurrentIndex = changeCurrentIndex { let oldIndexPath = IndexPath(item: currentIndex != fromIndex ? fromIndex : toIndex, section: 0) let newIndexPath = IndexPath(item: currentIndex, section: 0) @@ -266,21 +265,21 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa return cells } - // MARK: - UICollectionViewDelegateFlowLayout - + // MARK: - UICollectionViewDelegateFlowLayut + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize { guard let cellWidthValue = cachedCellWidths?[indexPath.row] else { fatalError("cachedCellWidths for \(indexPath.row) must not be nil") } return CGSize(width: cellWidthValue, height: collectionView.frame.size.height) } - + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard indexPath.item != currentIndex else { return } - + buttonBarView.moveTo(index: indexPath.item, animated: true, swipeDirection: .none, pagerScroll: .yes) shouldUpdateButtonBarView = false - + let oldIndexPath = IndexPath(item: currentIndex, section: 0) let newIndexPath = IndexPath(item: indexPath.item, section: 0) @@ -290,21 +289,20 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa if let changeCurrentIndexProgressive = changeCurrentIndexProgressive { changeCurrentIndexProgressive(cells.first!, cells.last!, 1, true, true) } - } - else { + } else { if let changeCurrentIndex = changeCurrentIndex { changeCurrentIndex(cells.first!, cells.last!, true) } } moveToViewController(at: indexPath.item) } - + // MARK: - UICollectionViewDataSource - + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return viewControllers.count } - + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? ButtonBarViewCell else { fatalError("UICollectionViewCell should be or extend from ButtonBarViewCell") @@ -312,9 +310,9 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa collectionViewDidLoad = true - let childController = viewControllers[indexPath.item] as! IndicatorInfoProvider + let childController = viewControllers[indexPath.item] as! IndicatorInfoProvider // swiftlint:disable:this force_cast let indicatorInfo = childController.indicatorInfo(for: self) - + cell.label.text = indicatorInfo.title cell.label.font = settings.style.buttonBarItemFont cell.label.textColor = settings.style.buttonBarItemTitleColor ?? cell.label.textColor @@ -328,41 +326,40 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa } configureCell(cell, indicatorInfo: indicatorInfo) - + if pagerBehaviour.isProgressiveIndicator { if let changeCurrentIndexProgressive = changeCurrentIndexProgressive { changeCurrentIndexProgressive(currentIndex == indexPath.item ? nil : cell, currentIndex == indexPath.item ? cell : nil, 1, true, false) } - } - else { + } else { if let changeCurrentIndex = changeCurrentIndex { changeCurrentIndex(currentIndex == indexPath.item ? nil : cell, currentIndex == indexPath.item ? cell : nil, false) } } return cell } - + // MARK: - UIScrollViewDelegate - + open override func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { super.scrollViewDidEndScrollingAnimation(scrollView) - + guard scrollView == containerView else { return } shouldUpdateButtonBarView = true } - - open func configureCell(_ cell: ButtonBarViewCell, indicatorInfo: IndicatorInfo){ + + open func configureCell(_ cell: ButtonBarViewCell, indicatorInfo: IndicatorInfo) { } - + private func calculateWidths() -> [CGFloat] { - let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout + let flowLayout = buttonBarView.collectionViewLayout as! UICollectionViewFlowLayout // swiftlint:disable:this force_cast let numberOfCells = viewControllers.count - + var minimumCellWidths = [CGFloat]() var collectionViewContentWidth: CGFloat = 0 - + for viewController in viewControllers { - let childController = viewController as! IndicatorInfoProvider + let childController = viewController as! IndicatorInfoProvider // swiftlint:disable:this force_cast let indicatorInfo = childController.indicatorInfo(for: self) switch buttonBarItemSpec! { case .cellClass(let widthCallback): @@ -375,30 +372,29 @@ open class ButtonBarPagerTabStripViewController: PagerTabStripViewController, Pa collectionViewContentWidth += width } } - + let cellSpacingTotal = CGFloat(numberOfCells - 1) * flowLayout.minimumLineSpacing collectionViewContentWidth += cellSpacingTotal - + let collectionViewAvailableVisibleWidth = buttonBarView.frame.size.width - flowLayout.sectionInset.left - flowLayout.sectionInset.right - + if !settings.style.buttonBarItemsShouldFillAvailableWidth || collectionViewAvailableVisibleWidth < collectionViewContentWidth { return minimumCellWidths - } - else { + } else { let stretchedCellWidthIfAllEqual = (collectionViewAvailableVisibleWidth - cellSpacingTotal) / CGFloat(numberOfCells) let generalMinimumCellWidth = calculateStretchedCellWidths(minimumCellWidths, suggestedStretchedCellWidth: stretchedCellWidthIfAllEqual, previousNumberOfLargeCells: 0) var stretchedCellWidths = [CGFloat]() - + for minimumCellWidthValue in minimumCellWidths { let cellWidth = (minimumCellWidthValue > generalMinimumCellWidth) ? minimumCellWidthValue : generalMinimumCellWidth stretchedCellWidths.append(cellWidth) } - + return stretchedCellWidths } } - + private var shouldUpdateButtonBarView = true private var collectionViewDidLoad = false - + } diff --git a/Sources/ButtonBarView.swift b/Sources/ButtonBarView.swift index 8832aca2..a204971e 100644 --- a/Sources/ButtonBarView.swift +++ b/Sources/ButtonBarView.swift @@ -44,13 +44,13 @@ public enum SelectedBarVerticalAlignment { } open class ButtonBarView: UICollectionView { - + open lazy var selectedBar: UIView = { [unowned self] in let bar = UIView(frame: CGRect(x: 0, y: self.frame.size.height - CGFloat(self.selectedBarHeight), width: 0, height: CGFloat(self.selectedBarHeight))) bar.layer.zPosition = 9999 return bar }() - + internal var selectedBarHeight: CGFloat = 4 { didSet { updateSelectedBarYPosition() @@ -59,96 +59,93 @@ open class ButtonBarView: UICollectionView { var selectedBarVerticalAlignment: SelectedBarVerticalAlignment = .bottom var selectedBarAlignment: SelectedBarAlignment = .center var selectedIndex = 0 - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) addSubview(selectedBar) } - + public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { super.init(frame: frame, collectionViewLayout: layout) addSubview(selectedBar) } - + open func moveTo(index: Int, animated: Bool, swipeDirection: SwipeDirection, pagerScroll: PagerScroll) { selectedIndex = index updateSelectedBarPosition(animated, swipeDirection: swipeDirection, pagerScroll: pagerScroll) } - - open func move(fromIndex: Int, toIndex: Int, progressPercentage: CGFloat,pagerScroll: PagerScroll) { + + open func move(fromIndex: Int, toIndex: Int, progressPercentage: CGFloat, pagerScroll: PagerScroll) { selectedIndex = progressPercentage > 0.5 ? toIndex : fromIndex - + let fromFrame = layoutAttributesForItem(at: IndexPath(item: fromIndex, section: 0))!.frame let numberOfItems = dataSource!.collectionView(self, numberOfItemsInSection: 0) - + var toFrame: CGRect - + if toIndex < 0 || toIndex > numberOfItems - 1 { if toIndex < 0 { let cellAtts = layoutAttributesForItem(at: IndexPath(item: 0, section: 0)) toFrame = cellAtts!.frame.offsetBy(dx: -cellAtts!.frame.size.width, dy: 0) - } - else { + } else { let cellAtts = layoutAttributesForItem(at: IndexPath(item: (numberOfItems - 1), section: 0)) toFrame = cellAtts!.frame.offsetBy(dx: cellAtts!.frame.size.width, dy: 0) } - } - else { + } else { toFrame = layoutAttributesForItem(at: IndexPath(item: toIndex, section: 0))!.frame } - + var targetFrame = fromFrame targetFrame.size.height = selectedBar.frame.size.height targetFrame.size.width += (toFrame.size.width - fromFrame.size.width) * progressPercentage targetFrame.origin.x += (toFrame.origin.x - fromFrame.origin.x) * progressPercentage - + selectedBar.frame = CGRect(x: targetFrame.origin.x, y: selectedBar.frame.origin.y, width: targetFrame.size.width, height: selectedBar.frame.size.height) - + var targetContentOffset: CGFloat = 0.0 if contentSize.width > frame.size.width { let toContentOffset = contentOffsetForCell(withFrame: toFrame, andIndex: toIndex) let fromContentOffset = contentOffsetForCell(withFrame: fromFrame, andIndex: fromIndex) - + targetContentOffset = fromContentOffset + ((toContentOffset - fromContentOffset) * progressPercentage) } - + setContentOffset(CGPoint(x: targetContentOffset, y: 0), animated: false) } - - open func updateSelectedBarPosition(_ animated: Bool, swipeDirection: SwipeDirection, pagerScroll: PagerScroll) -> Void { + + open func updateSelectedBarPosition(_ animated: Bool, swipeDirection: SwipeDirection, pagerScroll: PagerScroll) { var selectedBarFrame = selectedBar.frame - + let selectedCellIndexPath = IndexPath(item: selectedIndex, section: 0) let attributes = layoutAttributesForItem(at: selectedCellIndexPath) let selectedCellFrame = attributes!.frame - + updateContentOffset(animated: animated, pagerScroll: pagerScroll, toFrame: selectedCellFrame, toIndex: (selectedCellIndexPath as NSIndexPath).row) - + selectedBarFrame.size.width = selectedCellFrame.size.width selectedBarFrame.origin.x = selectedCellFrame.origin.x - + if animated { UIView.animate(withDuration: 0.3, animations: { [weak self] in self?.selectedBar.frame = selectedBarFrame }) - } - else { + } else { selectedBar.frame = selectedBarFrame } } - + // MARK: - Helpers - - private func updateContentOffset(animated: Bool, pagerScroll: PagerScroll, toFrame: CGRect, toIndex: Int) -> Void { + + private func updateContentOffset(animated: Bool, pagerScroll: PagerScroll, toFrame: CGRect, toIndex: Int) { guard pagerScroll != .no || (pagerScroll != .scrollOnlyIfOutOfScreen && (toFrame.origin.x < contentOffset.x || toFrame.origin.x >= (contentOffset.x + frame.size.width - contentInset.left))) else { return } let targetContentOffset = contentSize.width > frame.size.width ? contentOffsetForCell(withFrame: toFrame, andIndex: toIndex) : 0 setContentOffset(CGPoint(x: targetContentOffset, y: 0), animated: animated) } - + private func contentOffsetForCell(withFrame cellFrame: CGRect, andIndex index: Int) -> CGFloat { - let sectionInset = (collectionViewLayout as! UICollectionViewFlowLayout).sectionInset + let sectionInset = (collectionViewLayout as! UICollectionViewFlowLayout).sectionInset // swiftlint:disable:this force_cast var alignmentOffset: CGFloat = 0.0 - + switch selectedBarAlignment { case .left: alignmentOffset = sectionInset.left @@ -164,16 +161,16 @@ open class ButtonBarView: UICollectionView { let progress = index / (numberOfItems - 1) alignmentOffset = leftAlignmentOffset + (rightAlignmentOffset - leftAlignmentOffset) * CGFloat(progress) - cellHalfWidth } - + var contentOffset = cellFrame.origin.x - alignmentOffset contentOffset = max(0, contentOffset) contentOffset = min(contentSize.width - frame.size.width, contentOffset) return contentOffset } - + private func updateSelectedBarYPosition() { var selectedBarFrame = selectedBar.frame - + switch selectedBarVerticalAlignment { case .top: selectedBarFrame.origin.y = 0 @@ -182,11 +179,11 @@ open class ButtonBarView: UICollectionView { case .bottom: selectedBarFrame.origin.y = frame.size.height - selectedBarHeight } - + selectedBarFrame.size.height = selectedBarHeight selectedBar.frame = selectedBarFrame } - + override open func layoutSubviews() { super.layoutSubviews() updateSelectedBarYPosition() diff --git a/Sources/ButtonBarViewCell.swift b/Sources/ButtonBarViewCell.swift index 451f6808..f1165778 100644 --- a/Sources/ButtonBarViewCell.swift +++ b/Sources/ButtonBarViewCell.swift @@ -25,8 +25,8 @@ import Foundation open class ButtonBarViewCell: UICollectionViewCell { - + @IBOutlet open var imageView: UIImageView! @IBOutlet open var label: UILabel! - + } diff --git a/Sources/IndicatorInfo.swift b/Sources/IndicatorInfo.swift index 622fba17..fec4aa7b 100644 --- a/Sources/IndicatorInfo.swift +++ b/Sources/IndicatorInfo.swift @@ -25,20 +25,20 @@ import Foundation public struct IndicatorInfo { - + public var title: String? public var image: UIImage? public var highlightedImage: UIImage? - + public init(title: String?) { self.title = title } - + public init(image: UIImage?, highlightedImage: UIImage? = nil) { self.image = image self.highlightedImage = highlightedImage } - + public init(title: String?, image: UIImage?, highlightedImage: UIImage? = nil) { self.title = title self.image = image @@ -47,18 +47,17 @@ public struct IndicatorInfo { } - extension IndicatorInfo : ExpressibleByStringLiteral { - - public init(stringLiteral value: String){ + + public init(stringLiteral value: String) { title = value } - - public init(extendedGraphemeClusterLiteral value: String){ + + public init(extendedGraphemeClusterLiteral value: String) { title = value } - - public init(unicodeScalarLiteral value: String){ + + public init(unicodeScalarLiteral value: String) { title = value } } diff --git a/Sources/PagerTabStripBehaviour.swift b/Sources/PagerTabStripBehaviour.swift index 193d6789..e25ac03f 100644 --- a/Sources/PagerTabStripBehaviour.swift +++ b/Sources/PagerTabStripBehaviour.swift @@ -25,10 +25,10 @@ import Foundation public enum PagerTabStripBehaviour { - + case common(skipIntermediateViewControllers: Bool) case progressive(skipIntermediateViewControllers: Bool, elasticIndicatorLimit: Bool) - + public var skipIntermediateViewControllers: Bool { switch self { case .common(let skipIntermediateViewControllers): @@ -37,8 +37,7 @@ public enum PagerTabStripBehaviour { return skipIntermediateViewControllers } } - - + public var isProgressiveIndicator: Bool { switch self { case .common(_): @@ -47,7 +46,7 @@ public enum PagerTabStripBehaviour { return true } } - + public var isElasticIndicatorLimit: Bool { switch self { case .common(_): @@ -57,7 +56,3 @@ public enum PagerTabStripBehaviour { } } } - - - - diff --git a/Sources/PagerTabStripError.swift b/Sources/PagerTabStripError.swift index b8aa77e5..f3453656 100644 --- a/Sources/PagerTabStripError.swift +++ b/Sources/PagerTabStripError.swift @@ -25,5 +25,7 @@ import Foundation public enum PagerTabStripError: Error { - case viewControllerNotContainedInPagerTabStrip + + case viewControllerOutOfBounds + } diff --git a/Sources/PagerTabStripViewController.swift b/Sources/PagerTabStripViewController.swift index 672db6e0..01ae69d9 100644 --- a/Sources/PagerTabStripViewController.swift +++ b/Sources/PagerTabStripViewController.swift @@ -22,52 +22,50 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - import Foundation - // MARK: Protocols public protocol IndicatorInfoProvider { - + func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo + } public protocol PagerTabStripDelegate: class { - + func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int) } -public protocol PagerTabStripIsProgressiveDelegate : PagerTabStripDelegate { +public protocol PagerTabStripIsProgressiveDelegate: PagerTabStripDelegate { func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) } public protocol PagerTabStripDataSource: class { - + func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] } - -//MARK: PagerTabStripViewController +// MARK: PagerTabStripViewController open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { - + @IBOutlet weak public var containerView: UIScrollView! - + open weak var delegate: PagerTabStripDelegate? open weak var datasource: PagerTabStripDataSource? - + open var pagerBehaviour = PagerTabStripBehaviour.progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true) - + open private(set) var viewControllers = [UIViewController]() open private(set) var currentIndex = 0 open private(set) var preCurrentIndex = 0 // used *only* to store the index to which move when the pager becomes visible - + open var pageWidth: CGFloat { return containerView.bounds.width } - + open var scrollPercentage: CGFloat { if swipeDirection != .right { let module = fmod(containerView.contentOffset.x, pageWidth) @@ -75,17 +73,16 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { } return 1 - fmod(containerView.contentOffset.x >= 0 ? containerView.contentOffset.x : pageWidth + containerView.contentOffset.x, pageWidth) / pageWidth } - + open var swipeDirection: SwipeDirection { if containerView.contentOffset.x > lastContentOffset { return .left - } - else if containerView.contentOffset.x < lastContentOffset { + } else if containerView.contentOffset.x < lastContentOffset { return .right } return .none } - + override open func viewDidLoad() { super.viewDidLoad() let conteinerViewAux = containerView ?? { @@ -106,20 +103,20 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { containerView.showsHorizontalScrollIndicator = false containerView.isPagingEnabled = true reloadViewControllers() - + let childController = viewControllers[currentIndex] addChildViewController(childController) childController.view.autoresizingMask = [.flexibleHeight, .flexibleWidth] containerView.addSubview(childController.view) childController.didMove(toParentViewController: self) } - + open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) isViewAppearing = true childViewControllers.forEach { $0.beginAppearanceTransition(true, animated: animated) } } - + override open func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) lastSize = containerView.bounds.size @@ -131,32 +128,32 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { isViewAppearing = false childViewControllers.forEach { $0.endAppearanceTransition() } } - + open override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) childViewControllers.forEach { $0.beginAppearanceTransition(false, animated: animated) } } - + open override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) childViewControllers.forEach { $0.endAppearanceTransition() } } - - override open func viewDidLayoutSubviews(){ + + override open func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() updateIfNeeded() } - + open override var shouldAutomaticallyForwardAppearanceMethods: Bool { return false } - + open func moveToViewController(at index: Int, animated: Bool = true) { guard isViewLoaded && view.window != nil && currentIndex != index else { preCurrentIndex = index return } - + if animated && pagerBehaviour.skipIntermediateViewControllers && abs(currentIndex - index) > 1 { var tmpViewControllers = viewControllers let currentChildVC = viewControllers[currentIndex] @@ -168,32 +165,31 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { containerView.setContentOffset(CGPoint(x: pageOffsetForChild(at: fromIndex), y: 0), animated: false) (navigationController?.view ?? view).isUserInteractionEnabled = !animated containerView.setContentOffset(CGPoint(x: pageOffsetForChild(at: index), y: 0), animated: true) - } - else { + } else { (navigationController?.view ?? view).isUserInteractionEnabled = !animated containerView.setContentOffset(CGPoint(x: pageOffsetForChild(at: index), y: 0), animated: animated) } } - + open func moveTo(viewController: UIViewController, animated: Bool = true) { moveToViewController(at: viewControllers.index(of: viewController)!, animated: animated) } - - //MARK: - PagerTabStripDataSource - + + // MARK: - PagerTabStripDataSource + open func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { assertionFailure("Sub-class must implement the PagerTabStripDataSource viewControllers(for:) method") return [] } - - //MARK: - Helpers - + + // MARK: - Helpers + open func updateIfNeeded() { - if isViewLoaded && !lastSize.equalTo(containerView.bounds.size){ + if isViewLoaded && !lastSize.equalTo(containerView.bounds.size) { updateContent() } } - + open func canMoveTo(index: Int) -> Bool { return currentIndex != index && viewControllers.count > index } @@ -201,28 +197,28 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { open func pageOffsetForChild(at index: Int) -> CGFloat { return CGFloat(index) * containerView.bounds.width } - - open func offsetForChild(at index: Int) -> CGFloat{ + + open func offsetForChild(at index: Int) -> CGFloat { return (CGFloat(index) * containerView.bounds.width) + ((containerView.bounds.width - view.bounds.width) * 0.5) } - - open func offsetForChild(viewController: UIViewController) throws -> CGFloat{ + + open func offsetForChild(viewController: UIViewController) throws -> CGFloat { guard let index = viewControllers.index(of: viewController) else { - throw PagerTabStripError.viewControllerNotContainedInPagerTabStrip + throw PagerTabStripError.viewControllerOutOfBounds } return offsetForChild(at: index) } - + open func pageFor(contentOffset: CGFloat) -> Int { let result = virtualPageFor(contentOffset: contentOffset) return pageFor(virtualPage: result) } - + open func virtualPageFor(contentOffset: CGFloat) -> Int { return Int((contentOffset + 1.5 * pageWidth) / pageWidth) - 1 } - - open func pageFor(virtualPage: Int) -> Int{ + + open func pageFor(virtualPage: Int) -> Int { if virtualPage < 0 { return 0 } @@ -231,25 +227,24 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { } return virtualPage } - + open func updateContent() { if lastSize.width != containerView.bounds.size.width { lastSize = containerView.bounds.size containerView.contentOffset = CGPoint(x: pageOffsetForChild(at: currentIndex), y: 0) } lastSize = containerView.bounds.size - + let pagerViewControllers = pagerTabStripChildViewControllersForScrolling ?? viewControllers containerView.contentSize = CGSize(width: containerView.bounds.width * CGFloat(pagerViewControllers.count), height: containerView.contentSize.height) - + for (index, childController) in pagerViewControllers.enumerated() { let pageOffsetForChild = self.pageOffsetForChild(at: index) if fabs(containerView.contentOffset.x - pageOffsetForChild) < containerView.bounds.width { - if let _ = childController.parent { + if childController.parent != nil { childController.view.frame = CGRect(x: offsetForChild(at: index), y: 0, width: view.bounds.width, height: containerView.bounds.height) childController.view.autoresizingMask = [.flexibleHeight, .flexibleWidth] - } - else { + } else { childController.beginAppearanceTransition(true, animated: false) addChildViewController(childController) childController.view.frame = CGRect(x: offsetForChild(at: index), y: 0, width: view.bounds.width, height: containerView.bounds.height) @@ -258,9 +253,8 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { childController.didMove(toParentViewController: self) childController.endAppearanceTransition() } - } - else { - if let _ = childController.parent { + } else { + if childController.parent != nil { childController.beginAppearanceTransition(false, animated: false) childController.willMove(toParentViewController: nil) childController.view.removeFromSuperview() @@ -269,34 +263,31 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { } } } - + let oldCurrentIndex = currentIndex let virtualPage = virtualPageFor(contentOffset: containerView.contentOffset.x) let newCurrentIndex = pageFor(virtualPage: virtualPage) currentIndex = newCurrentIndex preCurrentIndex = currentIndex let changeCurrentIndex = newCurrentIndex != oldCurrentIndex - + if let progressiveDeledate = self as? PagerTabStripIsProgressiveDelegate, pagerBehaviour.isProgressiveIndicator { - + let (fromIndex, toIndex, scrollPercentage) = progressiveIndicatorData(virtualPage) progressiveDeledate.updateIndicator(for: self, fromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: scrollPercentage, indexWasChanged: changeCurrentIndex) - } - else{ + } else { delegate?.updateIndicator(for: self, fromIndex: min(oldCurrentIndex, pagerViewControllers.count - 1), toIndex: newCurrentIndex) } } - + open func reloadPagerTabStripView() { guard isViewLoaded else { return } - for childController in viewControllers { - if let _ = childController.parent { - childController.beginAppearanceTransition(false, animated: false) - childController.willMove(toParentViewController: nil) - childController.view.removeFromSuperview() - childController.removeFromParentViewController() - childController.endAppearanceTransition() - } + for childController in viewControllers where childController.parent != nil { + childController.beginAppearanceTransition(false, animated: false) + childController.willMove(toParentViewController: nil) + childController.view.removeFromSuperview() + childController.removeFromParentViewController() + childController.endAppearanceTransition() } reloadViewControllers() containerView.contentSize = CGSize(width: containerView.bounds.width * CGFloat(viewControllers.count), height: containerView.contentSize.height) @@ -307,22 +298,22 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { containerView.contentOffset = CGPoint(x: pageOffsetForChild(at: currentIndex), y: 0) updateContent() } - - //MARK: - UIScrollDelegate - + + // MARK: - UIScrollDelegate + open func scrollViewDidScroll(_ scrollView: UIScrollView) { if containerView == scrollView { updateContent() lastContentOffset = scrollView.contentOffset.x } } - + open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { if containerView == scrollView { lastPageNumber = pageFor(contentOffset: scrollView.contentOffset.x) } } - + open func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { if containerView == scrollView { pagerTabStripChildViewControllersForScrolling = nil @@ -330,9 +321,9 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { updateContent() } } - - //MARK: - Orientation - + + // MARK: - Orientation + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) isViewRotating = true @@ -345,40 +336,34 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { me.updateIfNeeded() } } - - - //MARK: Private - + + // MARK: Private + private func progressiveIndicatorData(_ virtualPage: Int) -> (Int, Int, CGFloat) { let count = viewControllers.count var fromIndex = currentIndex var toIndex = currentIndex let direction = swipeDirection - + if direction == .left { if virtualPage > count - 1 { fromIndex = count - 1 toIndex = count - } - else { + } else { if self.scrollPercentage >= 0.5 { fromIndex = max(toIndex - 1, 0) - } - else { + } else { toIndex = fromIndex + 1 } } - } - else if direction == .right { + } else if direction == .right { if virtualPage < 0 { fromIndex = 0 toIndex = -1 - } - else { + } else { if self.scrollPercentage > 0.5 { fromIndex = min(toIndex + 1, count - 1) - } - else { + } else { toIndex = fromIndex - 1 } } @@ -386,26 +371,26 @@ open class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { let scrollPercentage = pagerBehaviour.isElasticIndicatorLimit ? self.scrollPercentage : ((toIndex < 0 || toIndex >= count) ? 0.0 : self.scrollPercentage) return (fromIndex, toIndex, scrollPercentage) } - - private func reloadViewControllers(){ + + private func reloadViewControllers() { guard let dataSource = datasource else { fatalError("dataSource must not be nil") } viewControllers = dataSource.viewControllers(for: self) // viewControllers - guard viewControllers.count != 0 else { + guard !viewControllers.isEmpty else { fatalError("viewControllers(for:) should provide at least one child view controller") } viewControllers.forEach { if !($0 is IndicatorInfoProvider) { fatalError("Every view controller provided by PagerTabStripDataSource's viewControllers(for:) method must conform to InfoProvider") }} } - - private var pagerTabStripChildViewControllersForScrolling : [UIViewController]? + + private var pagerTabStripChildViewControllersForScrolling: [UIViewController]? private var lastPageNumber = 0 private var lastContentOffset: CGFloat = 0.0 private var pageBeforeRotate = 0 private var lastSize = CGSize(width: 0, height: 0) internal var isViewRotating = false internal var isViewAppearing = false - + } diff --git a/Sources/SegmentedPagerTabStripViewController.swift b/Sources/SegmentedPagerTabStripViewController.swift index e49ccb81..ea82881d 100644 --- a/Sources/SegmentedPagerTabStripViewController.swift +++ b/Sources/SegmentedPagerTabStripViewController.swift @@ -25,37 +25,36 @@ import Foundation public struct SegmentedPagerTabStripSettings { - + public struct Style { public var segmentedControlColor: UIColor? } - + public var style = Style() } - open class SegmentedPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripDelegate { - + @IBOutlet weak public var segmentedControl: UISegmentedControl! - + open var settings = SegmentedPagerTabStripSettings() - + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) pagerBehaviour = PagerTabStripBehaviour.common(skipIntermediateViewControllers: true) delegate = self datasource = self } - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) pagerBehaviour = PagerTabStripBehaviour.common(skipIntermediateViewControllers: true) delegate = self datasource = self } - + private(set) var shouldUpdateSegmentedControl = true - + open override func viewDidLoad() { super.viewDidLoad() segmentedControl = segmentedControl ?? UISegmentedControl() @@ -66,35 +65,34 @@ open class SegmentedPagerTabStripViewController: PagerTabStripViewController, Pa segmentedControl.addTarget(self, action: #selector(SegmentedPagerTabStripViewController.segmentedControlChanged(_:)), for: .valueChanged) reloadSegmentedControl() } - + open override func reloadPagerTabStripView() { super.reloadPagerTabStripView() if isViewLoaded { reloadSegmentedControl() } } - + func reloadSegmentedControl() { segmentedControl.removeAllSegments() - for (index, item) in viewControllers.enumerated(){ - let child = item as! IndicatorInfoProvider + for (index, item) in viewControllers.enumerated() { + let child = item as! IndicatorInfoProvider // swiftlint:disable:this force_cast if let image = child.indicatorInfo(for: self).image { segmentedControl.insertSegment(with: image, at: index, animated: false) - } - else { + } else { segmentedControl.insertSegment(withTitle: child.indicatorInfo(for: self).title, at: index, animated: false) } } segmentedControl.selectedSegmentIndex = currentIndex } - + func segmentedControlChanged(_ sender: UISegmentedControl) { let index = sender.selectedSegmentIndex updateIndicator(for: self, fromIndex: currentIndex, toIndex: index) shouldUpdateSegmentedControl = false moveToViewController(at: index) } - + // MARK: - PagerTabStripDelegate open func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int) { @@ -102,9 +100,9 @@ open class SegmentedPagerTabStripViewController: PagerTabStripViewController, Pa segmentedControl.selectedSegmentIndex = toIndex } } - + // MARK: - UIScrollViewDelegate - + open override func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { super.scrollViewDidEndScrollingAnimation(scrollView) shouldUpdateSegmentedControl = true diff --git a/Sources/TwitterPagerTabStripViewController.swift b/Sources/TwitterPagerTabStripViewController.swift index 5e18a995..c37215a2 100644 --- a/Sources/TwitterPagerTabStripViewController.swift +++ b/Sources/TwitterPagerTabStripViewController.swift @@ -25,7 +25,7 @@ import Foundation public struct TwitterPagerTabStripSettings { - + public struct Style { public var dotColor = UIColor(white: 1, alpha: 0.4) public var selectedDotColor = UIColor.white @@ -33,38 +33,38 @@ public struct TwitterPagerTabStripSettings { public var landscapeTitleFont = UIFont.systemFont(ofSize: 15) public var titleColor = UIColor.white } - + public var style = Style() } open class TwitterPagerTabStripViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate { - + open var settings = TwitterPagerTabStripSettings() - + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) pagerBehaviour = .progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true) delegate = self datasource = self } - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) pagerBehaviour = .progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true) delegate = self datasource = self } - + open override func viewDidLoad() { super.viewDidLoad() - + if titleView.superview == nil { navigationItem.titleView = titleView } - + // keep watching the frame of titleView titleView.addObserver(self, forKeyPath: "frame", options: [.new, .old], context: nil) - + guard let navigationController = navigationController else { fatalError("TwitterPagerTabStripViewController should be embedded in a UINavigationController") } @@ -77,11 +77,11 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page open override func reloadPagerTabStripView() { super.reloadPagerTabStripView() guard isViewLoaded else { return } - + reloadNavigationViewItems() setNavigationViewItemsPosition(updateAlpha: true) } - + // MARK: - PagerTabStripDelegate open func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) { @@ -91,11 +91,9 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page var xOffset: CGFloat = 0 if fromIndex < toIndex { xOffset = distance * CGFloat(fromIndex) + distance * progressPercentage - } - else if fromIndex > toIndex { + } else if fromIndex > toIndex { xOffset = distance * CGFloat(fromIndex) - distance * progressPercentage - } - else { + } else { xOffset = distance * CGFloat(fromIndex) } @@ -111,10 +109,10 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page open func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int) { fatalError() } - + open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard object as AnyObject === titleView && keyPath == "frame" && change?[NSKeyValueChangeKey.kindKey] as? UInt == NSKeyValueChange.setting.rawValue else { return } - + let oldRect = (change![NSKeyValueChangeKey.oldKey]! as AnyObject).cgRectValue let newRect = (change![NSKeyValueChangeKey.oldKey]! as AnyObject).cgRectValue if (oldRect?.equalTo(newRect!))! { @@ -122,26 +120,26 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page setNavigationViewItemsPosition(updateAlpha: true) } } - + deinit { if isViewLoaded { titleView.removeObserver(self, forKeyPath: "frame") } } - + open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() setNavigationViewItemsPosition(updateAlpha: false) } - + // MARK: - Helpers - + private lazy var titleView: UIView = { let navigationView = UIView() navigationView.autoresizingMask = [.flexibleWidth, .flexibleHeight] return navigationView }() - + private lazy var titleScrollView: UIScrollView = { [unowned self] in let titleScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 44)) titleScrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] @@ -156,7 +154,7 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page titleScrollView.alwaysBounceVertical = false return titleScrollView }() - + private lazy var pageControl: FXPageControl = { [unowned self] in let pageControl = FXPageControl() pageControl.backgroundColor = .clear @@ -167,7 +165,7 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page pageControl.isUserInteractionEnabled = false return pageControl }() - + private var childTitleLabels = [UILabel]() private func reloadNavigationViewItems() { @@ -175,9 +173,9 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page childTitleLabels.forEach { $0.removeFromSuperview() } childTitleLabels.removeAll() for (index, item) in viewControllers.enumerated() { - let child = item as! IndicatorInfoProvider + let child = item as! IndicatorInfoProvider // swiftlint:disable:this force_cast let indicatorInfo = child.indicatorInfo(for: self) - let navTitleLabel : UILabel = { + let navTitleLabel: UILabel = { let label = UILabel() label.text = indicatorInfo.title label.font = UIApplication.shared.statusBarOrientation.isPortrait ? settings.style.portraitTitleFont : settings.style.landscapeTitleFont @@ -191,7 +189,7 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page childTitleLabels.append(navTitleLabel) } } - + private func setNavigationViewItemsPosition(updateAlpha: Bool) { guard let distance = distanceValue else { return } let isPortrait = UIApplication.shared.statusBarOrientation.isPortrait @@ -207,30 +205,29 @@ open class TwitterPagerTabStripViewController: PagerTabStripViewController, Page label.frame = CGRect(x: originX, y: originY - 2, width: viewSize.width, height: viewSize.height) label.tag = index } - + let xOffset = distance * CGFloat(currentIndex) titleScrollView.contentOffset = CGPoint(x: xOffset, y: 0) - + pageControl.numberOfPages = childTitleLabels.count pageControl.currentPage = currentIndex let viewSize = pageControl.sizeForNumber(ofPages: childTitleLabels.count) let originX = distance - viewSize.width / 2 pageControl.frame = CGRect(x: originX, y: navBarHeight - 10, width: viewSize.width, height: viewSize.height) } - + private func setAlphaWith(offset: CGFloat, andDistance distance: CGFloat) { for (index, label) in childTitleLabels.enumerated() { label.alpha = { if offset < distance * CGFloat(index) { return (offset - distance * CGFloat(index - 1)) / distance - } - else { + } else { return 1 - ((offset - distance * CGFloat(index)) / distance) } }() } } - + private var distanceValue: CGFloat? { return navigationController.map { $0.navigationBar.convert($0.navigationBar.center, to: titleView) }?.x } diff --git a/Tests/XLPagerTabStripTests.swift b/Tests/XLPagerTabStripTests.swift index a47734ef..c959d637 100644 --- a/Tests/XLPagerTabStripTests.swift +++ b/Tests/XLPagerTabStripTests.swift @@ -9,27 +9,27 @@ import XCTest @testable import XLPagerTabStrip class XLPagerTabStripTests: XCTestCase { - + override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } - + func testPerformanceExample() { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. } } - + } diff --git a/XLPagerTabStrip.xcodeproj/project.pbxproj b/XLPagerTabStrip.xcodeproj/project.pbxproj index 466f8480..06752aec 100644 --- a/XLPagerTabStrip.xcodeproj/project.pbxproj +++ b/XLPagerTabStrip.xcodeproj/project.pbxproj @@ -192,6 +192,7 @@ 28F828791C494B2C00330CF4 /* Frameworks */, 28F8287A1C494B2C00330CF4 /* Headers */, 28F8287B1C494B2C00330CF4 /* Resources */, + CB25B8F81EBCF0CE00FEB0A2 /* SwiftLint */, ); buildRules = ( ); @@ -275,6 +276,23 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + CB25B8F81EBCF0CE00FEB0A2 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 28F828781C494B2C00330CF4 /* Sources */ = { isa = PBXSourcesBuildPhase; From 0b7dc7fe8c85813f8086b2df7c0c2a0b09e89b8f Mon Sep 17 00:00:00 2001 From: pera Date: Tue, 23 May 2017 11:57:40 -0300 Subject: [PATCH 2/2] Upgrade travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a7234a4f..203c568f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c -osx_image: xcode8 +osx_image: xcode8.3 env: - - DESTINATION="OS=10.0,name=iPhone 6s" SCHEME="XLPagerTabStrip" SDK=iphonesimulator10.0 + - DESTINATION="OS=10.3,name=iPhone 6s" SCHEME="XLPagerTabStrip" SDK=iphonesimulator10.3 before_install: - brew update #- brew outdated carthage || brew upgrade carthage