-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix controllers not popping when pressing a tab bar button #53
base: master
Are you sure you want to change the base?
Changes from all commits
8399e7c
d7656c8
bce34ba
49143f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// | ||
// RootTabBarController.swift | ||
// trySwift | ||
// | ||
// Created by Sash Zats on 3/2/18. | ||
// Copyright © 2018 NatashaTheRobot. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
|
||
class RootTabBarController: UITabBarController, UITabBarControllerDelegate { | ||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
self.delegate = self | ||
} | ||
|
||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { | ||
guard | ||
let splitViewController = viewController as? UISplitViewController, | ||
let navigationController = splitViewController.viewControllers.last as? UINavigationController | ||
else { | ||
return | ||
} | ||
|
||
// if several view controllers are in the stack, pop to the root | ||
if navigationController.viewControllers.count > 1 { | ||
navigationController.popToRootViewController(animated: true) | ||
} else { | ||
// if there's at least one view controller in the stack (which there always should be) | ||
if let firstController = navigationController.viewControllers.first { | ||
// we either delegate to the controller since it knows better how to scroll to the top | ||
if let scrollableToTop = firstController as? ScrollableToTop { | ||
scrollableToTop.scrollAfterTabTap() | ||
// or we find the topmost scroll view and scroll it to the top | ||
} else { | ||
firstController.view.findScrollSubview()?.setContentOffset(.zero, animated: true) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
protocol ScrollableToTop { | ||
func scrollAfterTabTap() | ||
} | ||
|
||
private extension UIView { | ||
func findScrollSubview() -> UIScrollView? { | ||
if let scrollView = self as? UIScrollView, | ||
scrollView.contentSize.width < scrollView.contentSize.height { | ||
return scrollView | ||
} | ||
for subview in self.subviews { | ||
if let scrollView = subview.findScrollSubview(), | ||
scrollView.contentSize.width < scrollView.contentSize.height { | ||
return scrollView | ||
} | ||
} | ||
return nil | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,8 +30,6 @@ class ScheduleViewController: ButtonBarPagerTabStripViewController { | |
buttonBarView.backgroundColor = .white | ||
settings.style.selectedBarBackgroundColor = .white | ||
buttonBarView.selectedBar.backgroundColor = .trySwiftAccentColor() | ||
|
||
tabBarController?.delegate = self | ||
} | ||
|
||
override func viewDidAppear(_ animated: Bool) { | ||
|
@@ -47,7 +45,6 @@ class ScheduleViewController: ButtonBarPagerTabStripViewController { | |
|
||
override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { | ||
return days.map { SessionsTableViewController(conferenceDay: $0, scheduleViewController: self) } | ||
|
||
} | ||
|
||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { | ||
|
@@ -59,6 +56,13 @@ class ScheduleViewController: ButtonBarPagerTabStripViewController { | |
} | ||
} | ||
|
||
extension ScheduleViewController: ScrollableToTop { | ||
func scrollAfterTabTap() { | ||
let controller = viewControllers[currentIndex] as! SessionsTableViewController | ||
controller.scrollAfterTabTap() | ||
} | ||
} | ||
|
||
private extension ScheduleViewController { | ||
|
||
@discardableResult | ||
|
@@ -77,19 +81,3 @@ private extension ScheduleViewController { | |
} | ||
} | ||
|
||
extension ScheduleViewController: UITabBarControllerDelegate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see the comment above, this functionality is handled in a |
||
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { | ||
guard | ||
tabBarController.selectedViewController === viewController, | ||
navigationController?.viewControllers.last === self | ||
else { return true } | ||
|
||
guard | ||
let index = moveToCorrectDate(animated: true), | ||
let controller = viewControllers[index] as? SessionsTableViewController | ||
else { return true } | ||
controller.scrollToCurrentSession(animated: true) | ||
|
||
return true | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import UIKit | |
import XLPagerTabStrip | ||
import TrySwiftData | ||
|
||
|
||
class SessionsTableViewController: UITableViewController { | ||
private lazy var needsToScrollToCurrentSession = Calendar.current.isDateInToday(conferenceDay.date) | ||
|
||
|
@@ -33,15 +34,15 @@ class SessionsTableViewController: UITableViewController { | |
super.viewDidLoad() | ||
|
||
configureTableView() | ||
|
||
if traitCollection.forceTouchCapability == .available { | ||
registerForPreviewing(with: self, sourceView: tableView) | ||
} | ||
} | ||
|
||
override func viewDidAppear(_ animated: Bool) { | ||
super.viewDidAppear(animated) | ||
|
||
if needsToScrollToCurrentSession { | ||
needsToScrollToCurrentSession = false | ||
scrollToCurrentSession(animated: false) | ||
|
@@ -55,32 +56,32 @@ class SessionsTableViewController: UITableViewController { | |
let isCollapsed = splitViewController?.isCollapsed, | ||
!isCollapsed, | ||
!didShowDetail else { return } | ||
|
||
didShowDetail = true | ||
scheduleViewController?.performSegue(withIdentifier: sessionDetailsSegue, sender: firstSelectableSessionVC) | ||
} | ||
} | ||
|
||
// MARK: - Table view data source | ||
extension SessionsTableViewController { | ||
|
||
override func numberOfSections(in tableView: UITableView) -> Int { | ||
return conferenceDay.sessionBlocks.count | ||
} | ||
|
||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | ||
return conferenceDay.sessionBlocks[section].sessions.count | ||
} | ||
|
||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | ||
let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SessionTableViewCell | ||
|
||
let session = conferenceDay.sessionBlocks[indexPath.section].sessions[indexPath.row] | ||
cell.configure(withSession: session) | ||
|
||
return cell | ||
} | ||
|
||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { | ||
let session = conferenceDay.sessionBlocks[section] | ||
let sessionDateFormatter = DateFormatter.sessionDateFormatter | ||
|
@@ -108,33 +109,33 @@ extension SessionsTableViewController: IndicatorInfoProvider { | |
} | ||
|
||
extension SessionsTableViewController: UIViewControllerPreviewingDelegate { | ||
|
||
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { | ||
guard let indexPath = tableView.indexPathForRow(at: location) else { return nil } | ||
// This will show the cell clearly and blur the rest of the screen for our peek. | ||
previewingContext.sourceRect = tableView.rectForRow(at: indexPath) | ||
let session = conferenceDay.sessionBlocks[indexPath.section].sessions[indexPath.row] | ||
return viewController(for: session) | ||
} | ||
|
||
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) { | ||
scheduleViewController?.performSegue(withIdentifier: sessionDetailsSegue, sender: viewControllerToCommit) | ||
} | ||
} | ||
|
||
extension SessionsTableViewController { | ||
|
||
func configureTableView() { | ||
|
||
tableView.register(SessionTableViewCell.self) | ||
|
||
tableView.estimatedRowHeight = 160 | ||
tableView.rowHeight = UITableViewAutomaticDimension | ||
} | ||
} | ||
|
||
private extension SessionsTableViewController { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not to brag but phabricator has a feature of hiding whitespace changes in review - it's pretty cool because it minimizes noise like this in review. I remember there was some sort of secret url parameter when reviewing pull requests… but to be honest I don't even know when I would want to see whitespace changes 🙂 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
func viewController(for session: Session) -> UIViewController? { | ||
switch session.type { | ||
case .talk, .lightningTalk: | ||
|
@@ -174,39 +175,39 @@ private extension SessionsTableViewController { | |
default: | ||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func sessionDetails(_ presentation: Presentation, session: Session) -> UIViewController { | ||
let storyboard = UIStoryboard(name: "Main", bundle: nil) | ||
let sessionDetailsVC = storyboard.instantiateViewController(withIdentifier: String(describing: SessionDetailsViewController.self)) as! SessionDetailsViewController | ||
sessionDetailsVC.session = session | ||
sessionDetailsVC.presentation = presentation | ||
return sessionDetailsVC | ||
} | ||
|
||
func officeHourDetails(_ speaker: Speaker, session: Session) -> UIViewController { | ||
let officeHoursVC = OfficeHoursDetailViewController() | ||
officeHoursVC.speaker = speaker | ||
officeHoursVC.session = session | ||
return officeHoursVC | ||
} | ||
|
||
func webDisplay(_ event: Event) -> UIViewController { | ||
let webViewController = WebDisplayViewController() | ||
webViewController.url = URL(string: event.website!) | ||
webViewController.displayTitle = event.title | ||
return webViewController | ||
} | ||
|
||
func webDisplay(_ sponsor: Sponsor) -> UIViewController { | ||
let webViewController = WebDisplayViewController() | ||
webViewController.url = URL(string: sponsor.url!) | ||
webViewController.displayTitle = sponsor.name | ||
return webViewController | ||
} | ||
|
||
func venueDetails(_ venue: Venue) -> UIViewController { | ||
let venueDetailsVC = VenueTableViewController(venue: venue) | ||
venueDetailsVC.tableView.contentInset = UIEdgeInsets(top: 80,left: 0,bottom: 0,right: 0) | ||
|
@@ -224,15 +225,21 @@ private extension SessionsTableViewController { | |
} | ||
|
||
extension SessionsTableViewController { | ||
|
||
func scrollToCurrentSession(animated: Bool) { | ||
let secondsFromGMT = TimeZone.current.secondsFromGMT() | ||
guard | ||
let date = Date().changed(second: secondsFromGMT), | ||
let section = conferenceDay.sessionBlocks.index(where: { date < $0.endTime }), | ||
!conferenceDay.sessionBlocks[section].sessions.isEmpty | ||
else { return } | ||
|
||
tableView.scrollToRow(at: IndexPath(row: 0, section: section), at: .top, animated: animated) | ||
} | ||
} | ||
|
||
extension SessionsTableViewController: ScrollableToTop { | ||
func scrollAfterTabTap() { | ||
scrollToCurrentSession(animated: true) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this since it's handled at a higher level now (RootTabBarController delegates this functionality via protocol conformance now)