Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // BaseViewController.swift
- // LushApp
- //
- // Created by Shagun Madhikarmi on 06/10/2014.
- // Copyright (c) 2014 Lush. All rights reserved.
- //
- import UIKit
- import ReachabilitySwift
- import Crashlytics
- class BaseViewController: GAITrackedViewController {
- private(set) var loadingView: LoadingView?
- var refreshControl: UIRefreshControl?
- var reachability: Reachability? = nil
- var errorView: ErrorView?
- var basketViewController: BasketViewController?
- var themeStyle: ThemeStyle {
- get {
- return .Light
- }
- }
- var showNavigationBar: Bool {
- get {
- return true
- }
- }
- var appDelegate: AppDelegate {
- get {
- return UIApplication.sharedApplication().delegate as! AppDelegate
- }
- }
- var online: Bool = false
- var wifiConnection: Bool = true
- // MARK: - View lifecycle
- override func viewDidLoad() {
- super.viewDidLoad()
- self.setupUserInterface()
- }
- override func viewWillAppear(animated: Bool) {
- super.viewWillAppear(animated)
- self.addBasketNotificationObservers()
- self.addSlideNotificationObservers()
- self.addSessionExpiredNotificationObservers()
- self.addSessionLoginNotificationObservers()
- self.updateTheme()
- self.updateBasketCounter(animated: false)
- }
- override func viewDidAppear(animated: Bool) {
- super.viewDidAppear(animated)
- // Sets first element to be read by voice over only if navigation bar not hidden
- if let titleView = self.navigationItem.titleView {
- self.navigationController?.setupAccessibilityDefaultItem(titleView)
- }
- }
- override func viewWillDisappear(animated: Bool) {
- super.viewWillDisappear(animated)
- self.removeBasketNotificationObservers()
- self.removeSlideNotificationObservers()
- self.removeSessionExpiredNotificationObservers()
- self.removeSessionLoginNotificationObservers()
- BasketManager.sharedInstance.cancelNetworkRequests()
- ImageProxy.sharedInstance.cancelNetworkRequests()
- if let reachability = self.reachability {
- reachability.stopNotifier()
- reachability.whenReachable = nil
- reachability.whenUnreachable = nil
- }
- self.reachability = nil
- }
- // MARK: - User Interface
- func setupUserInterface() {
- self.setupNavigationBar()
- }
- func setupReachabilityNotifier() {
- // Setup Reachability Notification only if needed
- if self.reachability == nil {
- self.reachability = try? Reachability.reachabilityForInternetConnection()
- self.reachability?.whenReachable = { reachability in
- if reachability.isReachableViaWiFi() {
- self.wifiConnection = true
- } else {
- self.wifiConnection = false
- }
- self.online = true
- }
- self.reachability?.whenUnreachable = { reachability in
- self.online = false
- }
- do {
- try self.reachability?.startNotifier()
- //
- if let wifiResult = self.reachability?.isReachableViaWiFi() {
- self.wifiConnection = wifiResult
- } else {
- self.wifiConnection = false
- }
- if let onlineResult = self.reachability?.isReachable() {
- self.online = onlineResult
- } else {
- self.online = false
- }
- } catch {
- self.wifiConnection = false
- self.online = false
- }
- }
- }
- func updateUserInterface() {
- self.hideLoadingView()
- }
- func loadDataAndUpdateUserInterface() {
- self.hideErrorView()
- if let refreshControl = self.refreshControl where refreshControl.refreshing {
- self.hideLoadingView()
- } else {
- self.showLoadingView()
- }
- }
- // MARK: - Theme
- func updateTheme() {
- if (self.showNavigationBar) {
- ThemeManager.sharedInstance.setThemeStyle(self.themeStyle, viewController: self, animated: true)
- } else {
- ThemeManager.sharedInstance.setThemeStyle(self.themeStyle)
- }
- self.showOrHideNavigationBar(animated: true)
- }
- // MARK: - Notifications
- private func addBasketNotificationObservers() {
- NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(BaseViewController.basketUpdated(_:)), name: kBasketManagerBasketUpdatedNotification, object: nil)
- }
- private func addSlideNotificationObservers() {
- if (self.showNavigationBar) {
- NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(BaseViewController.slideMenuWillClose(_:)), name: kSlideMenuWillCloseNotification, object: nil)
- }
- }
- private func removeBasketNotificationObservers() {
- NSNotificationCenter.defaultCenter().removeObserver(self, name: kBasketManagerBasketUpdatedNotification, object: nil)
- }
- private func removeSlideNotificationObservers() {
- NSNotificationCenter.defaultCenter().removeObserver(self, name: kSlideMenuWillCloseNotification, object: nil)
- }
- func slideMenuWillClose(notification: NSNotification) {
- self.updateTheme()
- // Re enable swipe to pop back
- self.enablePopGesture(true)
- }
- func basketUpdated(notification: NSNotification) {
- self.updateBasketCounter(animated: true)
- }
- // MARK: - User Session
- func addSessionLoginNotificationObservers() {
- NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(BaseViewController.sessionLoggedIn(_:)), name: kSessionManagerSessionLoggedIn, object: nil)
- }
- func removeSessionLoginNotificationObservers() {
- NSNotificationCenter.defaultCenter().removeObserver(self, name: kSessionManagerSessionLoggedIn, object: nil)
- }
- func addSessionExpiredNotificationObservers() {
- // Abstract Method: Implement if necessary
- }
- func removeSessionExpiredNotificationObservers() {
- // Abstract Method: Implement if necessary
- }
- func sessionExpired(notification: NSNotification) {
- // Call this when wanting to notify the user of session expired
- self.showUserSessionTimeoutAlert()
- }
- func sessionLoggedIn(notification: NSNotification) {
- // Abstract Method: Implement if necessary
- }
- func refreshUserSession() {
- if SessionManager.sharedInstance.isUserLoggedIn {
- SessionManager.sharedInstance.refreshSessionIfNeeded({ () -> () in
- }, failure: { (error) -> () in
- })
- }
- }
- // MARK: - Navigation Bar
- private func setupNavigationBar() {
- if let navigationController = self.navigationController {
- if (navigationController.viewControllers.count > 1) {
- // Setting navigation bar back button
- let backBarButtonItem: UIBarButtonItem = UIBarButtonItem.backBarButtonItem()
- if let backBarButton = backBarButtonItem.customView as? UIButton {
- backBarButton.addTarget(self, action: #selector(BaseViewController.didPressBackBarButtonItem(_:)), forControlEvents: .TouchUpInside)
- }
- if let screenTitle = self.navigationController?.previousToTopViewControllerTitle() {
- backBarButtonItem.accessibilityLabel = String.localizedString("BACK_BUTTON_ACCESSIBILITY_LABEL", comment: "") + screenTitle
- }
- self.navigationItem.leftBarButtonItem = backBarButtonItem
- }
- // Setting navigation bar basket button
- let basketBarButtonItem: UIBarButtonItem = UIBarButtonItem.basketBarButtonItem()
- if let basketBarButton = basketBarButtonItem.customView as? BadgeButtonControl {
- let basketCounter: Int = BasketManager.sharedInstance.numberOfItemsInBasket()
- basketBarButton.setBadgeCounter(basketCounter, animated: false)
- basketBarButton.addTarget(self, action: #selector(BaseViewController.didPressBasketBarButtonItem(_:)), forControlEvents: .TouchUpInside)
- }
- self.navigationItem.rightBarButtonItem = basketBarButtonItem
- }
- }
- func showOrHideNavigationBar(animated animated: Bool = true) {
- self.showOrHideNavigationBar(self.showNavigationBar, animated: animated)
- }
- private func showOrHideNavigationBar(visible: Bool, animated: Bool = true) {
- if let navigationController = self.navigationController {
- let duration: NSTimeInterval = (animated) ? 0.275 : 0.0
- UIView.animateWithDuration(duration, animations: { () -> Void in
- navigationController.navigationBar.hidden = !visible
- })
- }
- }
- // MARK: - Back Button
- func didPressBackBarButtonItem(sender: UIBarButtonItem) {
- if let navigationController = self.navigationController {
- navigationController.popViewControllerAnimated(true)
- }
- }
- // MARK: - Basket Button
- private func updateBasketCounter(animated animated: Bool) {
- let basketBarButtonItem: UIBarButtonItem? = self.navigationItem.rightBarButtonItem
- if let basketBarButton = basketBarButtonItem?.customView as? BadgeButtonControl {
- let basketCounter: Int = BasketManager.sharedInstance.numberOfItemsInBasket()
- basketBarButton.setBadgeCounter(basketCounter, animated: animated)
- }
- }
- func showNavigationBarBasketButtonItem() {
- self.showOrHideNavigationBarBasketButtonItem(true)
- }
- func hideNavigationBarBasketButtonItem() {
- self.showOrHideNavigationBarBasketButtonItem(false)
- }
- func showOrHideNavigationBarBasketButtonItem(visible: Bool, animated: Bool = true) {
- if (self.navigationController != nil) {
- self.navigationItem.rightBarButtonItem = nil
- self.navigationController!.navigationItem.rightBarButtonItem = nil
- if visible {
- // Setting navigation bar basket button
- let basketBarButtonItem: UIBarButtonItem = UIBarButtonItem.basketBarButtonItem()
- if let basketBarButton = basketBarButtonItem.customView as? BadgeButtonControl {
- basketBarButton.addTarget(self, action: #selector(BaseViewController.didPressBasketBarButtonItem(_:)), forControlEvents: .TouchUpInside)
- basketBarButton.image = ThemeManager.sharedInstance.theme!.basketButtonImage()
- basketBarButton.highlightedImage = ThemeManager.sharedInstance.theme!.basketButtonHighlightedImage()
- let basketCounter: Int = BasketManager.sharedInstance.numberOfItemsInBasket()
- basketBarButton.setBadgeCounter(basketCounter, animated: animated)
- }
- self.navigationItem.rightBarButtonItem = basketBarButtonItem
- self.navigationController!.navigationItem.rightBarButtonItem = basketBarButtonItem
- } else {
- self.navigationItem.rightBarButtonItem = nil
- self.navigationController!.navigationItem.rightBarButtonItem = nil
- }
- }
- }
- func didPressBasketBarButtonItem(sender: UIBarButtonItem) {
- // End Editing
- self.view.endEditing(true)
- // Disable swype to pop back
- self.enablePopGesture(false)
- // Lazy load / Open Basket [We must make sure that the Basket View Controller is kept in memory or else UIAlertViewDelegate callback causes app to crash]
- if self.basketViewController == nil {
- self.basketViewController = BasketViewController()
- }
- if let slideMenuViewController = self.slideMenuViewController(), let basketViewController = self.basketViewController {
- slideMenuViewController.openRightViewController(basketViewController)
- }
- }
- // MARK: - Error handling
- func handleError(error: NSError?) {
- let message: String = NSError.localizedMessage(error)
- self.showErrorWithMessage(message)
- }
- func showErrorWithMessage(message: String) {
- let title: String = String.localizedString("COMMON_ERROR_TITLE", comment: "")
- self.showErrorWithMessage(title: title, message: message)
- }
- func showErrorWithMessage(title title: String, message: String) {
- // If there's a loading view hide that first
- self.hideLoadingView()
- self.hideErrorView()
- // Create view
- self.errorView = ErrorView(frame: CGRectZero)
- self.view.addSubview(self.errorView!)
- // layout
- self.errorView?.translatesAutoresizingMaskIntoConstraints = false
- self.errorView?.addCenterXConstraint(toView: self.errorView?.superview)
- self.errorView?.addCenterYConstraint(toView: self.errorView?.superview)
- self.errorView?.addLeftConstraint(toView: self.errorView?.superview, relation: .Equal, constant: 0)
- self.errorView?.addRightConstraint(toView: self.errorView?.superview, relation: .Equal, constant: 0)
- self.errorView?.addBottomConstraint(toView: self.errorView?.superview, attribute: .Bottom, relation: .LessThanOrEqual, constant: 0)
- // content
- self.errorView?.setTitle(title, subtitle: message)
- // accessibility
- self.errorView?.accessibilityIdentifier = AccessibilityHelper.accessibilityIdentifierWithPrefix("COMMON_ERROR", suffixes: ["MESSAGE"])
- if (kDEBUG) {
- self.errorView!.backgroundColor = UIColor.orangeColor()
- }
- }
- func hideErrorView() {
- self.errorView?.removeFromSuperview()
- self.errorView = nil
- }
- // MARK: - Order Exceptions
- func getErrorAlertTitleAndMessageFromUpdateOrder(order: Order?, error: NSError?) -> (String, String)? {
- var alertTitleAndMessage: (String, String)?
- let basketManager: BasketManager = BasketManager.sharedInstance
- let basketItems: [BasketItem] = basketManager.getBasketItems()
- let previousBasketItems: [BasketItem] = basketManager.previousBasketItems
- var title: String?
- var message: String?
- if let updatedOrder = order where updatedOrder.hasOrderExceptions {
- // Note. since we have detected exceptions find the appropriate messsage
- if (previousBasketItems.count > basketItems.count) {
- let productVariantTitles = ProductVariant.joinedProductVariantTitles(updatedOrder.exceptionProductVariants)
- message = NSString(format: String.localizedString("COMMON_ERROR_EXCEPTION_PRODUCTS_REMOVED", comment: ""), productVariantTitles) as String
- title = String.localizedString("COMMON_ERROR_EXCEPTION_PRODUCTS_REMOVED_ALERT_TITLE", comment: "")
- } else if (basketManager.numberOfItemsPreviouslyInBasket() > basketManager.numberOfItemsInBasket()) {
- message = String.localizedString("COMMON_ERROR_EXCEPTION_PRODUCTS_UPDATED", comment: "")
- title = String.localizedString("COMMON_ERROR_EXCEPTION_PRODUCTS_UPDATED_ALERT_TITLE", comment: "")
- } else {
- message = String.localizedString("COMMON_ERROR_MESSAGE_UPDATE_ORDER", comment: "")
- title = String.localizedString("COMMON_ERROR_TITLE", comment: "")
- }
- } else if let serverError = error {
- if (serverError.isNotAvailableError()) {
- message = String.localizedString("COMMON_ERROR_NO_AVAILABLE_LINE_ITEMS", comment: "")
- title = String.localizedString("COMMON_ERROR_NO_AVAILABLE_LINE_ITEMS_ALERT_TITLE", comment: "")
- } else if (serverError.domain == kErrorDomain && (serverError.code == ErrorCode.CreateOrder.rawValue)) {
- message = String.localizedString("COMMON_ERROR_MESSAGE_CREATE_ORDER", comment: "")
- title = String.localizedString("COMMON_ERROR_TITLE", comment: "")
- } else if (serverError.domain == kErrorDomain && (serverError.code == ErrorCode.UpdateOrder.rawValue)) {
- message = String.localizedString("COMMON_ERROR_MESSAGE_UPDATE_ORDER", comment: "")
- title = String.localizedString("COMMON_ERROR_TITLE", comment: "")
- } else {
- message = String.localizedString("COMMON_ERROR_MESSAGE_UPDATE_ORDER", comment: "")
- title = String.localizedString("COMMON_ERROR_TITLE", comment: "")
- }
- }
- if let alertMessage = message, let alertTitle = title {
- alertTitleAndMessage = (alertTitle, alertMessage)
- }
- return alertTitleAndMessage
- }
- func showUpdateOrderAlertControllerIfNecessary(order: Order?, error: NSError?, completion: () -> ()) {
- if let alertTitleAndMessage = self.getErrorAlertTitleAndMessageFromUpdateOrder(order, error: error) {
- let title: String = alertTitleAndMessage.0
- let message: String = alertTitleAndMessage.1
- self.showUpdateOrderAlertController(title, message: message, completion: completion)
- } else {
- completion()
- }
- }
- func showUpdateOrderAlertController(title: String, message: String, completion: (() -> ())) {
- let alertController: UIAlertController = UIAlertController(title: title, message: message as String, preferredStyle: .Alert)
- let okAction: UIAlertAction = UIAlertAction(title: String.localizedString("OK", comment: ""), style: .Default, handler: { (alertAction) -> Void in
- let basketItems = BasketManager.sharedInstance.getBasketItems()
- if (basketItems.isEmpty) {
- BasketManager.sharedInstance.order?.restoreDefaultValues()
- self.navigationController?.dismissViewControllerAnimated(true, completion: { () -> Void in
- completion()
- })
- } else {
- completion()
- }
- })
- alertController.addAction(okAction)
- self.presentViewController(alertController, animated: true, completion: nil)
- }
- // MARK: - Navigation Controller methods
- func fadeInAndAnimateToBack() -> () {
- UIView.animateWithDuration(
- kFadeAnimationDuration,
- delay: 0,
- options: .CurveEaseIn,
- animations: {
- self.view.alpha = 1
- }, completion: nil)
- }
- func searchNavigationController()-> SearchNavigationController? {
- var searchNavigationController: SearchNavigationController? = nil
- if (self.navigationController != nil) {
- if (self.navigationController!.dynamicType === SearchNavigationController.self) {
- searchNavigationController = self.navigationController as? SearchNavigationController
- }
- }
- return searchNavigationController
- }
- // MARK: - Loading
- func showLoadingView() {
- if self.loadingView != nil {
- self.hideLoadingView()
- }
- // Create view
- self.loadingView = LoadingView(frame: CGRectZero)
- self.view.addSubview(self.loadingView! )
- self.loadingView?.translatesAutoresizingMaskIntoConstraints = false
- self.loadingView?.fillSuperView(UIEdgeInsetsZero)
- self.loadingView?.startAnimating()
- }
- func showLoadingViewWithBackground() {
- self.showLoadingView()
- self.loadingView?.backgroundColor = UIColor.lightBackgroundColor()
- }
- func hideLoadingView() {
- weak var weakSelf = self
- if let strongSelf = weakSelf {
- strongSelf.loadingView?.stopAnimating()
- strongSelf.loadingView?.removeFromSuperview()
- strongSelf.loadingView = nil
- }
- }
- // MARK: - Gestures
- private func enablePopGesture(enable: Bool) {
- if let navigationController = self.navigationController {
- navigationController.interactivePopGestureRecognizer?.enabled = (enable && navigationController.viewControllers.count > 1)
- }
- }
- // MARK: - Send Analytics
- func sendAnalyticsEvent(category: String, action: String, label: String, value:NSNumber?) {
- let tracker = GAI.sharedInstance().defaultTracker
- let event = GAIDictionaryBuilder.createEventWithCategory(category, action:action, label: label, value: value)
- if let builtEvent = event.build() as [NSObject : AnyObject]! {
- tracker.send(builtEvent)
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement