Adds SideMenu and company view
This commit is contained in:
1
Podfile
1
Podfile
@@ -17,6 +17,7 @@ target 'pocloud' do
|
||||
pod 'Firebase/Core'
|
||||
pod 'Firebase/Database'
|
||||
pod 'Firebase/Auth'
|
||||
pod 'SideMenu'
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ PODS:
|
||||
- Realm/Headers (3.6.0)
|
||||
- RealmSwift (3.6.0):
|
||||
- Realm (= 3.6.0)
|
||||
- SideMenu (4.0.0)
|
||||
- SVProgressHUD (2.2.5)
|
||||
- SwiftChart (1.0.1)
|
||||
- SwiftyJSON (4.1.0)
|
||||
@@ -62,6 +63,7 @@ DEPENDENCIES:
|
||||
- Kingfisher
|
||||
- PromiseKit/Alamofire
|
||||
- RealmSwift
|
||||
- SideMenu
|
||||
- SVProgressHUD
|
||||
- SwiftChart
|
||||
- SwiftyJSON
|
||||
@@ -84,6 +86,7 @@ SPEC REPOS:
|
||||
- PromiseKit
|
||||
- Realm
|
||||
- RealmSwift
|
||||
- SideMenu
|
||||
- SVProgressHUD
|
||||
- SwiftChart
|
||||
- SwiftyJSON
|
||||
@@ -105,10 +108,11 @@ SPEC CHECKSUMS:
|
||||
PromiseKit: 6788ce1a0ed5448b83d4aaf56b9fc49fb7647d32
|
||||
Realm: 08b464b462d4f31bbd4ba5f5a1c8722ef0a700b7
|
||||
RealmSwift: 973e1499c44ab571f894c2c908e2db450be280c3
|
||||
SideMenu: 70ee5657df63ec3382660ec4ef470bf1cf5db07d
|
||||
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
|
||||
SwiftChart: ba767a678d568a5ee22d419e146a0582865e1aff
|
||||
SwiftyJSON: c29297daf073d2aa016295d5809cdd68045c39b3
|
||||
|
||||
PODFILE CHECKSUM: c9a181d8ad3c0f7b81cea07af27c66668ea4e83f
|
||||
PODFILE CHECKSUM: f920b0139378aa95335e4e152b9daa8cfaf65705
|
||||
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
6
Pods/Manifest.lock
generated
6
Pods/Manifest.lock
generated
@@ -49,6 +49,7 @@ PODS:
|
||||
- Realm/Headers (3.6.0)
|
||||
- RealmSwift (3.6.0):
|
||||
- Realm (= 3.6.0)
|
||||
- SideMenu (4.0.0)
|
||||
- SVProgressHUD (2.2.5)
|
||||
- SwiftChart (1.0.1)
|
||||
- SwiftyJSON (4.1.0)
|
||||
@@ -62,6 +63,7 @@ DEPENDENCIES:
|
||||
- Kingfisher
|
||||
- PromiseKit/Alamofire
|
||||
- RealmSwift
|
||||
- SideMenu
|
||||
- SVProgressHUD
|
||||
- SwiftChart
|
||||
- SwiftyJSON
|
||||
@@ -84,6 +86,7 @@ SPEC REPOS:
|
||||
- PromiseKit
|
||||
- Realm
|
||||
- RealmSwift
|
||||
- SideMenu
|
||||
- SVProgressHUD
|
||||
- SwiftChart
|
||||
- SwiftyJSON
|
||||
@@ -105,10 +108,11 @@ SPEC CHECKSUMS:
|
||||
PromiseKit: 6788ce1a0ed5448b83d4aaf56b9fc49fb7647d32
|
||||
Realm: 08b464b462d4f31bbd4ba5f5a1c8722ef0a700b7
|
||||
RealmSwift: 973e1499c44ab571f894c2c908e2db450be280c3
|
||||
SideMenu: 70ee5657df63ec3382660ec4ef470bf1cf5db07d
|
||||
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
|
||||
SwiftChart: ba767a678d568a5ee22d419e146a0582865e1aff
|
||||
SwiftyJSON: c29297daf073d2aa016295d5809cdd68045c39b3
|
||||
|
||||
PODFILE CHECKSUM: c9a181d8ad3c0f7b81cea07af27c66668ea4e83f
|
||||
PODFILE CHECKSUM: f920b0139378aa95335e4e152b9daa8cfaf65705
|
||||
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
8465
Pods/Pods.xcodeproj/project.pbxproj
generated
8465
Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
19
Pods/SideMenu/LICENSE
generated
Normal file
19
Pods/SideMenu/LICENSE
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015 Jonathan Kent <contact@jonkent.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
684
Pods/SideMenu/Pod/Classes/SideMenuManager.swift
generated
Normal file
684
Pods/SideMenu/Pod/Classes/SideMenuManager.swift
generated
Normal file
@@ -0,0 +1,684 @@
|
||||
//
|
||||
// SideMenuManager.swift
|
||||
//
|
||||
// Created by Jon Kent on 12/6/15.
|
||||
// Copyright © 2015 Jon Kent. All rights reserved.
|
||||
//
|
||||
|
||||
/* Example usage:
|
||||
// Define the menus
|
||||
SideMenuManager.menuLeftNavigationController = storyboard!.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as? UISideMenuNavigationController
|
||||
SideMenuManager.menuRightNavigationController = storyboard!.instantiateViewController(withIdentifier: "RightMenuNavigationController") as? UISideMenuNavigationController
|
||||
|
||||
// Enable gestures. The left and/or right menus must be set up above for these to work.
|
||||
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
|
||||
SideMenuManager.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
*/
|
||||
|
||||
@objcMembers
|
||||
open class SideMenuManager : NSObject {
|
||||
|
||||
@objc public enum MenuPushStyle : Int {
|
||||
case defaultBehavior,
|
||||
popWhenPossible,
|
||||
replace,
|
||||
preserve,
|
||||
preserveAndHideBackButton,
|
||||
subMenu
|
||||
}
|
||||
|
||||
@objc public enum MenuPresentMode : Int {
|
||||
case menuSlideIn,
|
||||
viewSlideOut,
|
||||
viewSlideInOut,
|
||||
menuDissolveIn
|
||||
}
|
||||
|
||||
// Bounds which has been allocated for the app on the whole device screen
|
||||
internal static var appScreenRect: CGRect {
|
||||
let appWindowRect = UIApplication.shared.keyWindow?.bounds ?? UIWindow().bounds
|
||||
return appWindowRect
|
||||
}
|
||||
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved..
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
open var menuPushStyle: MenuPushStyle = .defaultBehavior
|
||||
|
||||
/**
|
||||
The presentation mode of the menu.
|
||||
|
||||
There are four modes in MenuPresentMode:
|
||||
- menuSlideIn: Menu slides in over of the existing view.
|
||||
- viewSlideOut: The existing view slides out to reveal the menu.
|
||||
- viewSlideInOut: The existing view slides out while the menu slides in.
|
||||
- menuDissolveIn: The menu dissolves in over the existing view controller.
|
||||
*/
|
||||
open var menuPresentMode: MenuPresentMode = .viewSlideOut
|
||||
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
open var menuAllowPushOfSameClassTwice = true
|
||||
|
||||
/**
|
||||
Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width or 240 points, whichever is smaller.
|
||||
|
||||
Note that each menu's width can be overridden using the `menuWidth` property on any `UISideMenuNavigationController` instance.
|
||||
*/
|
||||
open var menuWidth: CGFloat = min(round(min((appScreenRect.width), (appScreenRect.height)) * 0.75), 240)
|
||||
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationPresentDuration: Double = 0.35
|
||||
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationDismissDuration: Double = 0.35
|
||||
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationCompleteGestureDuration: Double = 0.35
|
||||
|
||||
/// Amount to fade the existing view controller when the menu is presented. Default is 0 for no fade. Set to 1 to fade completely.
|
||||
open var menuAnimationFadeStrength: CGFloat = 0
|
||||
|
||||
/// The amount to scale the existing view controller or the menu view controller depending on the `menuPresentMode`. Default is 1 for no scaling. Less than 1 will shrink, greater than 1 will grow.
|
||||
open var menuAnimationTransformScaleFactor: CGFloat = 1
|
||||
|
||||
/// The background color behind menu animations. Depending on the animation settings this may not be visible. If `menuFadeStatusBar` is true, this color is used to fade it. Default is black.
|
||||
open var menuAnimationBackgroundColor: UIColor?
|
||||
|
||||
/// The shadow opacity around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 0.5 for 50% opacity.
|
||||
open var menuShadowOpacity: Float = 0.5
|
||||
|
||||
/// The shadow color around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is black.
|
||||
open var menuShadowColor = UIColor.black
|
||||
|
||||
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
|
||||
open var menuShadowRadius: CGFloat = 5
|
||||
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. Default is false.
|
||||
open var menuPresentingViewControllerUserInteractionEnabled: Bool = false
|
||||
|
||||
/// The strength of the parallax effect on the existing view controller. Does not apply to `menuPresentMode` when set to `ViewSlideOut`. Default is 0.
|
||||
open var menuParallaxStrength: Int = 0
|
||||
|
||||
/// Draws the `menuAnimationBackgroundColor` behind the status bar. Default is true.
|
||||
open var menuFadeStatusBar = true
|
||||
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationOptions: UIViewAnimationOptions = .curveEaseInOut
|
||||
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationUsingSpringWithDamping: CGFloat = 1
|
||||
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open var menuDismissOnPush = true
|
||||
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
open var menuAlwaysAnimate = false
|
||||
|
||||
/// Default instance of SideMenuManager.
|
||||
open static let `default` = SideMenuManager()
|
||||
|
||||
/// Default instance of SideMenuManager (objective-C).
|
||||
open class var defaultManager: SideMenuManager {
|
||||
get {
|
||||
return SideMenuManager.default
|
||||
}
|
||||
}
|
||||
|
||||
internal var transition: SideMenuTransition!
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
transition = SideMenuTransition(sideMenuManager: self)
|
||||
}
|
||||
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell.
|
||||
*/
|
||||
open var menuBlurEffectStyle: UIBlurEffectStyle? {
|
||||
didSet {
|
||||
if oldValue != menuBlurEffectStyle {
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The left menu.
|
||||
open var menuLeftNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
guard menuLeftNavigationController != newValue, menuLeftNavigationController?.presentingViewController == nil else {
|
||||
return
|
||||
}
|
||||
menuLeftNavigationController?.locked = false
|
||||
removeMenuBlurForMenu(menuLeftNavigationController)
|
||||
}
|
||||
didSet {
|
||||
guard menuLeftNavigationController != oldValue else {
|
||||
return
|
||||
}
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuLeftNavigationController cannot be modified while it's presented.")
|
||||
menuLeftNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
|
||||
setupNavigationController(menuLeftNavigationController, leftSide: true)
|
||||
}
|
||||
}
|
||||
|
||||
/// The right menu.
|
||||
open var menuRightNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
guard menuRightNavigationController != newValue, menuRightNavigationController?.presentingViewController == nil else {
|
||||
return
|
||||
}
|
||||
removeMenuBlurForMenu(menuRightNavigationController)
|
||||
}
|
||||
didSet {
|
||||
guard menuRightNavigationController != oldValue else {
|
||||
return
|
||||
}
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuRightNavigationController cannot be modified while it's presented.")
|
||||
menuRightNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
setupNavigationController(menuRightNavigationController, leftSide: false)
|
||||
}
|
||||
}
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuLeftSwipeToDismissGesture)
|
||||
}
|
||||
}
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuRightSwipeToDismissGesture)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setupGesture(gesture: UIPanGestureRecognizer?) {
|
||||
guard let gesture = gesture else {
|
||||
return
|
||||
}
|
||||
|
||||
gesture.addTarget(transition, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
}
|
||||
|
||||
fileprivate func setupNavigationController(_ forMenu: UISideMenuNavigationController?, leftSide: Bool) {
|
||||
guard let forMenu = forMenu else {
|
||||
return
|
||||
}
|
||||
|
||||
forMenu.transitioningDelegate = transition
|
||||
forMenu.modalPresentationStyle = .overFullScreen
|
||||
forMenu.leftSide = leftSide
|
||||
|
||||
if forMenu.sideMenuManager != self {
|
||||
#if !STFU_SIDEMENU
|
||||
if forMenu.sideMenuManager?.menuLeftNavigationController == forMenu {
|
||||
print("SideMenu Warning: \(String(describing: forMenu.self)) was already assigned to the menuLeftNavigationController of \(String(describing: forMenu.sideMenuManager!.self)). When using multiple SideMenuManagers you may want to use new instances of UISideMenuNavigationController instead of existing instances to avoid crashes if the menu is presented more than once.")
|
||||
} else if forMenu.sideMenuManager?.menuRightNavigationController == forMenu {
|
||||
print("SideMenu Warning: \(String(describing: forMenu.self)) was already assigned to the menuRightNavigationController of \(String(describing: forMenu.sideMenuManager!.self)). When using multiple SideMenuManagers you may want to use new instances of UISideMenuNavigationController instead of existing instances to avoid crashes if the menu is presented more than once.")
|
||||
}
|
||||
#endif
|
||||
forMenu.sideMenuManager = self
|
||||
}
|
||||
|
||||
forMenu.locked = true
|
||||
|
||||
if menuEnableSwipeGestures {
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.cancelsTouchesInView = false
|
||||
forMenu.view.addGestureRecognizer(exitPanGesture)
|
||||
if leftSide {
|
||||
menuLeftSwipeToDismissGesture = exitPanGesture
|
||||
} else {
|
||||
menuRightSwipeToDismissGesture = exitPanGesture
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures minimal lag when revealing the menu for the first time using gestures by loading the view:
|
||||
let _ = forMenu.topViewController?.view
|
||||
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
|
||||
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
|
||||
open var menuEnableSwipeGestures: Bool = true {
|
||||
didSet {
|
||||
menuLeftSwipeToDismissGesture?.view?.removeGestureRecognizer(menuLeftSwipeToDismissGesture!)
|
||||
menuRightSwipeToDismissGesture?.view?.removeGestureRecognizer(menuRightSwipeToDismissGesture!)
|
||||
setupNavigationController(menuLeftNavigationController, leftSide: true)
|
||||
setupNavigationController(menuRightNavigationController, leftSide: false)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func updateMenuBlurIfNecessary() {
|
||||
if let menuLeftNavigationController = self.menuLeftNavigationController {
|
||||
setupMenuBlurForMenu(menuLeftNavigationController)
|
||||
}
|
||||
if let menuRightNavigationController = self.menuRightNavigationController {
|
||||
setupMenuBlurForMenu(menuRightNavigationController)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setupMenuBlurForMenu(_ forMenu: UISideMenuNavigationController?) {
|
||||
removeMenuBlurForMenu(forMenu)
|
||||
|
||||
guard let forMenu = forMenu,
|
||||
let menuBlurEffectStyle = menuBlurEffectStyle,
|
||||
let view = forMenu.topViewController?.view,
|
||||
!UIAccessibilityIsReduceTransparencyEnabled() else {
|
||||
return
|
||||
}
|
||||
|
||||
if forMenu.originalMenuBackgroundColor == nil {
|
||||
forMenu.originalMenuBackgroundColor = view.backgroundColor
|
||||
}
|
||||
|
||||
let blurEffect = UIBlurEffect(style: menuBlurEffectStyle)
|
||||
let blurView = UIVisualEffectView(effect: blurEffect)
|
||||
view.backgroundColor = UIColor.clear
|
||||
if let tableViewController = forMenu.topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = blurView
|
||||
tableViewController.tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||
tableViewController.tableView.reloadData()
|
||||
} else {
|
||||
blurView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
blurView.frame = view.bounds
|
||||
view.insertSubview(blurView, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func removeMenuBlurForMenu(_ forMenu: UISideMenuNavigationController?) {
|
||||
guard let forMenu = forMenu,
|
||||
let originalMenuBackgroundColor = forMenu.originalMenuBackgroundColor,
|
||||
let view = forMenu.topViewController?.view else {
|
||||
return
|
||||
}
|
||||
|
||||
view.backgroundColor = originalMenuBackgroundColor
|
||||
forMenu.originalMenuBackgroundColor = nil
|
||||
|
||||
if let tableViewController = forMenu.topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = nil
|
||||
tableViewController.tableView.separatorEffect = nil
|
||||
tableViewController.tableView.reloadData()
|
||||
} else if let blurView = view.subviews[0] as? UIVisualEffectView {
|
||||
blurView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Adds screen edge gestures to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add gestures to.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for. If unspecified, gestures will be added for both sides.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
var array = [UIScreenEdgePanGestureRecognizer]()
|
||||
|
||||
let newScreenEdgeGesture = { () -> UIScreenEdgePanGestureRecognizer in
|
||||
let screenEdgeGestureRecognizer = UIScreenEdgePanGestureRecognizer()
|
||||
screenEdgeGestureRecognizer.cancelsTouchesInView = true
|
||||
toView.addGestureRecognizer(screenEdgeGestureRecognizer)
|
||||
array.append(screenEdgeGestureRecognizer)
|
||||
return screenEdgeGestureRecognizer
|
||||
}
|
||||
|
||||
if forMenu != .right {
|
||||
let leftScreenEdgeGestureRecognizer = newScreenEdgeGesture()
|
||||
leftScreenEdgeGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuLeftScreenEdge(_:)))
|
||||
leftScreenEdgeGestureRecognizer.edges = .left
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if menuLeftNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuLeftNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if forMenu != .left {
|
||||
let rightScreenEdgeGestureRecognizer = newScreenEdgeGesture()
|
||||
rightScreenEdgeGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuRightScreenEdge(_:)))
|
||||
rightScreenEdgeGestureRecognizer.edges = .right
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if menuRightNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuRightNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a pan edge gesture to a view to present menus.
|
||||
|
||||
- Parameter toView: The view to add a pan gesture to.
|
||||
|
||||
- Returns: The pan gesture added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer {
|
||||
let panGestureRecognizer = UIPanGestureRecognizer()
|
||||
panGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuPan(_:)))
|
||||
toView.addGestureRecognizer(panGestureRecognizer)
|
||||
|
||||
if menuLeftNavigationController ?? menuRightNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddPanGestureToPresent called before menuLeftNavigationController or menuRightNavigationController have been defined. Gestures will not work without a menu.")
|
||||
}
|
||||
|
||||
return panGestureRecognizer
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecations, to be removed at a future date.
|
||||
extension SideMenuManager {
|
||||
|
||||
@available(*, deprecated, renamed: "default.menuPushStyle", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPushStyle: MenuPushStyle {
|
||||
get {
|
||||
return `default`.menuPushStyle
|
||||
}
|
||||
set {
|
||||
`default`.menuPushStyle = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuPresentMode", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPresentMode: MenuPresentMode {
|
||||
get {
|
||||
return `default`.menuPresentMode
|
||||
}
|
||||
set {
|
||||
`default`.menuPresentMode = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAllowPushOfSameClassTwice", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAllowPushOfSameClassTwice: Bool {
|
||||
get {
|
||||
return `default`.menuAllowPushOfSameClassTwice
|
||||
}
|
||||
set {
|
||||
`default`.menuAllowPushOfSameClassTwice = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuWidth", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuWidth: CGFloat {
|
||||
get {
|
||||
return `default`.menuWidth
|
||||
}
|
||||
set {
|
||||
`default`.menuWidth = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationPresentDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationPresentDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationPresentDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationPresentDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationDismissDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationDismissDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationDismissDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationDismissDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationCompleteGestureDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationCompleteGestureDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationCompleteGestureDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationCompleteGestureDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationFadeStrength", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationFadeStrength: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationFadeStrength
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationFadeStrength = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationTransformScaleFactor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationTransformScaleFactor: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationTransformScaleFactor
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationTransformScaleFactor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationBackgroundColor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationBackgroundColor: UIColor? {
|
||||
get {
|
||||
return `default`.menuAnimationBackgroundColor
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationBackgroundColor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowOpacity", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowOpacity: Float {
|
||||
get {
|
||||
return `default`.menuShadowOpacity
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowOpacity = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowColor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowColor: UIColor {
|
||||
get {
|
||||
return `default`.menuShadowColor
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowColor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowRadius", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowRadius: CGFloat {
|
||||
get {
|
||||
return `default`.menuShadowRadius
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowRadius = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuPresentingViewControllerUserInteractionEnabled", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPresentingViewControllerUserInteractionEnabled: Bool {
|
||||
get {
|
||||
return `default`.menuPresentingViewControllerUserInteractionEnabled
|
||||
}
|
||||
set {
|
||||
`default`.menuPresentingViewControllerUserInteractionEnabled = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuParallaxStrength", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuParallaxStrength: Int {
|
||||
get {
|
||||
return `default`.menuParallaxStrength
|
||||
}
|
||||
set {
|
||||
`default`.menuParallaxStrength = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuFadeStatusBar", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuFadeStatusBar: Bool {
|
||||
get {
|
||||
return `default`.menuFadeStatusBar
|
||||
}
|
||||
set {
|
||||
`default`.menuFadeStatusBar = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationOptions", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationOptions: UIViewAnimationOptions {
|
||||
get {
|
||||
return `default`.menuAnimationOptions
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationOptions = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationUsingSpringWithDamping", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationUsingSpringWithDamping: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationUsingSpringWithDamping
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationUsingSpringWithDamping = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationInitialSpringVelocity", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationInitialSpringVelocity: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationInitialSpringVelocity
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationInitialSpringVelocity = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuDismissOnPush", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuDismissOnPush: Bool {
|
||||
get {
|
||||
return `default`.menuDismissOnPush
|
||||
}
|
||||
set {
|
||||
`default`.menuDismissOnPush = newValue
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .subMenu` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .subMenu` instead.")
|
||||
open static var menuAllowSubmenus: Bool {
|
||||
get {
|
||||
return menuPushStyle == .subMenu
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .subMenu
|
||||
}
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .popWhenPossible` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .popWhenPossible` instead.")
|
||||
open static var menuAllowPopIfPossible: Bool {
|
||||
get {
|
||||
return menuPushStyle == .popWhenPossible
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .popWhenPossible
|
||||
}
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .replace` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .replace` instead.")
|
||||
open static var menuReplaceOnPush: Bool {
|
||||
get {
|
||||
return menuPushStyle == .replace
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .replace
|
||||
}
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuBlurEffectStyle", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuBlurEffectStyle: UIBlurEffectStyle? {
|
||||
get {
|
||||
return `default`.menuBlurEffectStyle
|
||||
}
|
||||
set {
|
||||
`default`.menuBlurEffectStyle = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuLeftNavigationController", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuLeftNavigationController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return `default`.menuLeftNavigationController
|
||||
}
|
||||
set {
|
||||
`default`.menuLeftNavigationController = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuRightNavigationController", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuRightNavigationController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return `default`.menuRightNavigationController
|
||||
}
|
||||
set {
|
||||
`default`.menuRightNavigationController = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuLeftSwipeToDismissGesture", message: "SideMenuManager class methods deprecated.")
|
||||
open static weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get {
|
||||
return `default`.menuLeftSwipeToDismissGesture
|
||||
}
|
||||
set {
|
||||
`default`.menuLeftSwipeToDismissGesture = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuRightSwipeToDismissGesture", message: "SideMenuManager class methods deprecated.")
|
||||
open static weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get {
|
||||
return `default`.menuRightSwipeToDismissGesture
|
||||
}
|
||||
set {
|
||||
`default`.menuRightSwipeToDismissGesture = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuEnableSwipeGestures", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuEnableSwipeGestures: Bool {
|
||||
get {
|
||||
return `default`.menuEnableSwipeGestures
|
||||
}
|
||||
set {
|
||||
`default`.menuEnableSwipeGestures = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAddScreenEdgePanGesturesToPresent", message: "SideMenuManager class methods deprecated.")
|
||||
@discardableResult open class func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
return `default`.menuAddScreenEdgePanGesturesToPresent(toView: toView, forMenu: forMenu)
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAddPanGestureToPresent", message: "SideMenuManager class methods deprecated.")
|
||||
@discardableResult open class func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer {
|
||||
return `default`.menuAddPanGestureToPresent(toView: toView)
|
||||
}
|
||||
}
|
||||
575
Pods/SideMenu/Pod/Classes/SideMenuTransition.swift
generated
Normal file
575
Pods/SideMenu/Pod/Classes/SideMenuTransition.swift
generated
Normal file
@@ -0,0 +1,575 @@
|
||||
//
|
||||
// SideMenuTransition.swift
|
||||
// Pods
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
//
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
fileprivate var presenting = false
|
||||
fileprivate var interactive = false
|
||||
fileprivate weak var originalSuperview: UIView?
|
||||
fileprivate weak var activeGesture: UIGestureRecognizer?
|
||||
fileprivate var switchMenus = false {
|
||||
didSet {
|
||||
if switchMenus {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
fileprivate var menuWidth: CGFloat {
|
||||
get {
|
||||
let overriddenWidth = menuViewController?.menuWidth ?? 0
|
||||
if overriddenWidth > CGFloat.ulpOfOne {
|
||||
return overriddenWidth
|
||||
}
|
||||
return sideMenuManager.menuWidth
|
||||
}
|
||||
}
|
||||
internal weak var sideMenuManager: SideMenuManager!
|
||||
internal weak var mainViewController: UIViewController?
|
||||
internal weak var menuViewController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return presentDirection == .left ? sideMenuManager.menuLeftNavigationController : sideMenuManager.menuRightNavigationController
|
||||
}
|
||||
}
|
||||
internal var presentDirection: UIRectEdge = .left
|
||||
internal weak var tapView: UIView? {
|
||||
didSet {
|
||||
guard let tapView = tapView else {
|
||||
return
|
||||
}
|
||||
|
||||
tapView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
let exitTapGesture = UITapGestureRecognizer()
|
||||
exitTapGesture.addTarget(self, action: #selector(SideMenuTransition.handleHideMenuTap(_:)))
|
||||
tapView.addGestureRecognizer(exitPanGesture)
|
||||
tapView.addGestureRecognizer(exitTapGesture)
|
||||
}
|
||||
}
|
||||
internal weak var statusBarView: UIView? {
|
||||
didSet {
|
||||
guard let statusBarView = statusBarView else {
|
||||
return
|
||||
}
|
||||
|
||||
statusBarView.backgroundColor = sideMenuManager.menuAnimationBackgroundColor ?? UIColor.black
|
||||
statusBarView.isUserInteractionEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
required public init(sideMenuManager: SideMenuManager) {
|
||||
super.init()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector:#selector(handleNotification), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector:#selector(handleNotification), name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
self.sideMenuManager = sideMenuManager
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
fileprivate static var visibleViewController: UIViewController? {
|
||||
get {
|
||||
return getVisibleViewController(forViewController: UIApplication.shared.keyWindow?.rootViewController)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class func getVisibleViewController(forViewController: UIViewController?) -> UIViewController? {
|
||||
if let navigationController = forViewController as? UINavigationController {
|
||||
return getVisibleViewController(forViewController: navigationController.visibleViewController)
|
||||
}
|
||||
if let tabBarController = forViewController as? UITabBarController {
|
||||
return getVisibleViewController(forViewController: tabBarController.selectedViewController)
|
||||
}
|
||||
if let splitViewController = forViewController as? UISplitViewController {
|
||||
return getVisibleViewController(forViewController: splitViewController.viewControllers.last)
|
||||
}
|
||||
if let presentedViewController = forViewController?.presentedViewController {
|
||||
return getVisibleViewController(forViewController: presentedViewController)
|
||||
}
|
||||
|
||||
return forViewController
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuLeftScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = .left
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuRightScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = .right
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
pan.isEnabled = false
|
||||
pan.isEnabled = true
|
||||
return
|
||||
} else if pan.state != .began && pan.state != .changed {
|
||||
activeGesture = nil
|
||||
}
|
||||
|
||||
// how much distance have we panned in reference to the parent view?
|
||||
guard let view = mainViewController?.view ?? pan.view else {
|
||||
return
|
||||
}
|
||||
|
||||
let transform = view.transform
|
||||
view.transform = .identity
|
||||
let translation = pan.translation(in: pan.view!)
|
||||
view.transform = transform
|
||||
|
||||
// do some math to translate this to a percentage based value
|
||||
if !interactive {
|
||||
if translation.x == 0 {
|
||||
return // not sure which way the user is swiping yet, so do nothing
|
||||
}
|
||||
|
||||
if !(pan is UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = translation.x > 0 ? .left : .right
|
||||
}
|
||||
|
||||
if let menuViewController = menuViewController, let visibleViewController = SideMenuTransition.visibleViewController {
|
||||
interactive = true
|
||||
visibleViewController.present(menuViewController, animated: true, completion: nil)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let direction: CGFloat = presentDirection == .left ? 1 : -1
|
||||
let distance = translation.x / menuWidth
|
||||
// now lets deal with different states that the gesture recognizer sends
|
||||
switch (pan.state) {
|
||||
case .began, .changed:
|
||||
if pan is UIScreenEdgePanGestureRecognizer {
|
||||
update(min(distance * direction, 1))
|
||||
} else if distance > 0 && presentDirection == .right && sideMenuManager.menuLeftNavigationController != nil {
|
||||
presentDirection = .left
|
||||
switchMenus = true
|
||||
} else if distance < 0 && presentDirection == .left && sideMenuManager.menuRightNavigationController != nil {
|
||||
presentDirection = .right
|
||||
switchMenus = true
|
||||
} else {
|
||||
update(min(distance * direction, 1))
|
||||
}
|
||||
default:
|
||||
interactive = false
|
||||
view.transform = .identity
|
||||
let velocity = pan.velocity(in: pan.view!).x * direction
|
||||
view.transform = transform
|
||||
if velocity >= 100 || velocity >= -50 && abs(distance) >= 0.5 {
|
||||
finish()
|
||||
} else {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func handleHideMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
pan.isEnabled = false
|
||||
pan.isEnabled = true
|
||||
return
|
||||
}
|
||||
|
||||
let translation = pan.translation(in: pan.view!)
|
||||
let direction:CGFloat = presentDirection == .left ? -1 : 1
|
||||
let distance = translation.x / menuWidth * direction
|
||||
|
||||
switch (pan.state) {
|
||||
|
||||
case .began:
|
||||
interactive = true
|
||||
mainViewController?.dismiss(animated: true, completion: nil)
|
||||
case .changed:
|
||||
update(max(min(distance, 1), 0))
|
||||
default:
|
||||
interactive = false
|
||||
let velocity = pan.velocity(in: pan.view!).x * direction
|
||||
if velocity >= 100 || velocity >= -50 && distance >= 0.5 {
|
||||
finish()
|
||||
activeGesture = nil
|
||||
} else {
|
||||
cancel()
|
||||
activeGesture = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func handleHideMenuTap(_ tap: UITapGestureRecognizer) {
|
||||
menuViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@discardableResult internal func hideMenuStart() -> SideMenuTransition {
|
||||
guard let menuView = menuViewController?.view,
|
||||
let mainView = mainViewController?.view else {
|
||||
return self
|
||||
}
|
||||
|
||||
mainView.transform = .identity
|
||||
mainView.alpha = 1
|
||||
mainView.frame.origin = .zero
|
||||
menuView.transform = .identity
|
||||
menuView.frame.origin.y = 0
|
||||
menuView.frame.size.width = menuWidth
|
||||
menuView.frame.size.height = mainView.frame.height // in case status bar height changed
|
||||
var statusBarFrame = UIApplication.shared.statusBarFrame
|
||||
let statusBarOffset = SideMenuManager.appScreenRect.size.height - mainView.frame.maxY
|
||||
// For in-call status bar, height is normally 40, which overlaps view. Instead, calculate height difference
|
||||
// of view and set height to fill in remaining space.
|
||||
if statusBarOffset >= CGFloat.ulpOfOne {
|
||||
statusBarFrame.size.height = statusBarOffset
|
||||
}
|
||||
statusBarView?.frame = statusBarFrame
|
||||
statusBarView?.alpha = 0
|
||||
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
|
||||
case .viewSlideOut:
|
||||
menuView.alpha = 1 - sideMenuManager.menuAnimationFadeStrength
|
||||
menuView.frame.origin.x = presentDirection == .left ? 0 : mainView.frame.width - menuWidth
|
||||
menuView.transform = CGAffineTransform(scaleX: sideMenuManager.menuAnimationTransformScaleFactor, y: sideMenuManager.menuAnimationTransformScaleFactor)
|
||||
|
||||
case .viewSlideInOut, .menuSlideIn:
|
||||
menuView.alpha = 1
|
||||
menuView.frame.origin.x = presentDirection == .left ? -menuWidth : mainView.frame.width
|
||||
|
||||
case .menuDissolveIn:
|
||||
menuView.alpha = 0
|
||||
menuView.frame.origin.x = presentDirection == .left ? 0 : mainView.frame.width - menuWidth
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func hideMenuComplete() -> SideMenuTransition {
|
||||
let menuView = menuViewController?.view
|
||||
let mainView = mainViewController?.view
|
||||
|
||||
tapView?.removeFromSuperview()
|
||||
statusBarView?.removeFromSuperview()
|
||||
mainView?.motionEffects.removeAll()
|
||||
mainView?.layer.shadowOpacity = 0
|
||||
menuView?.layer.shadowOpacity = 0
|
||||
if let topNavigationController = mainViewController as? UINavigationController {
|
||||
topNavigationController.interactivePopGestureRecognizer!.isEnabled = true
|
||||
}
|
||||
if let originalSuperview = originalSuperview, let mainView = mainViewController?.view {
|
||||
originalSuperview.addSubview(mainView)
|
||||
let y = originalSuperview.bounds.height - mainView.frame.size.height
|
||||
mainView.frame.origin.y = max(y, 0)
|
||||
}
|
||||
|
||||
originalSuperview = nil
|
||||
mainViewController = nil
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func presentMenuStart() -> SideMenuTransition {
|
||||
guard let menuView = menuViewController?.view,
|
||||
let mainView = mainViewController?.view else {
|
||||
return self
|
||||
}
|
||||
|
||||
menuView.alpha = 1
|
||||
menuView.transform = .identity
|
||||
menuView.frame.size.width = menuWidth
|
||||
let size = SideMenuManager.appScreenRect.size
|
||||
menuView.frame.origin.x = presentDirection == .left ? 0 : size.width - menuWidth
|
||||
mainView.transform = .identity
|
||||
mainView.frame.size.width = size.width
|
||||
let statusBarOffset = size.height - menuView.bounds.height
|
||||
mainView.bounds.size.height = size.height - max(statusBarOffset, 0)
|
||||
mainView.frame.origin.y = 0
|
||||
var statusBarFrame = UIApplication.shared.statusBarFrame
|
||||
// For in-call status bar, height is normally 40, which overlaps view. Instead, calculate height difference
|
||||
// of view and set height to fill in remaining space.
|
||||
if statusBarOffset >= CGFloat.ulpOfOne {
|
||||
statusBarFrame.size.height = statusBarOffset
|
||||
}
|
||||
tapView?.transform = .identity
|
||||
tapView?.bounds = mainView.bounds
|
||||
statusBarView?.frame = statusBarFrame
|
||||
statusBarView?.alpha = 1
|
||||
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
mainView.layer.shadowColor = sideMenuManager.menuShadowColor.cgColor
|
||||
mainView.layer.shadowRadius = sideMenuManager.menuShadowRadius
|
||||
mainView.layer.shadowOpacity = sideMenuManager.menuShadowOpacity
|
||||
mainView.layer.shadowOffset = CGSize(width: 0, height: 0)
|
||||
let direction:CGFloat = presentDirection == .left ? 1 : -1
|
||||
mainView.frame.origin.x = direction * menuView.frame.width
|
||||
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
if sideMenuManager.menuBlurEffectStyle == nil {
|
||||
menuView.layer.shadowColor = sideMenuManager.menuShadowColor.cgColor
|
||||
menuView.layer.shadowRadius = sideMenuManager.menuShadowRadius
|
||||
menuView.layer.shadowOpacity = sideMenuManager.menuShadowOpacity
|
||||
menuView.layer.shadowOffset = CGSize(width: 0, height: 0)
|
||||
}
|
||||
mainView.frame.origin.x = 0
|
||||
}
|
||||
|
||||
if sideMenuManager.menuPresentMode != .viewSlideOut {
|
||||
mainView.transform = CGAffineTransform(scaleX: sideMenuManager.menuAnimationTransformScaleFactor, y: sideMenuManager.menuAnimationTransformScaleFactor)
|
||||
if sideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
tapView?.transform = mainView.transform
|
||||
}
|
||||
mainView.alpha = 1 - sideMenuManager.menuAnimationFadeStrength
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func presentMenuComplete() -> SideMenuTransition {
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .menuSlideIn, .menuDissolveIn, .viewSlideInOut:
|
||||
if let mainView = mainViewController?.view, sideMenuManager.menuParallaxStrength != 0 {
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -sideMenuManager.menuParallaxStrength
|
||||
horizontal.maximumRelativeValue = sideMenuManager.menuParallaxStrength
|
||||
|
||||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
||||
vertical.minimumRelativeValue = -sideMenuManager.menuParallaxStrength
|
||||
vertical.maximumRelativeValue = sideMenuManager.menuParallaxStrength
|
||||
|
||||
let group = UIMotionEffectGroup()
|
||||
group.motionEffects = [horizontal, vertical]
|
||||
mainView.addMotionEffect(group)
|
||||
}
|
||||
case .viewSlideOut: break;
|
||||
}
|
||||
if let topNavigationController = mainViewController as? UINavigationController {
|
||||
topNavigationController.interactivePopGestureRecognizer!.isEnabled = false
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@objc internal func handleNotification(notification: NSNotification) {
|
||||
guard menuViewController?.presentedViewController == nil &&
|
||||
menuViewController?.presentingViewController != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
if let originalSuperview = originalSuperview, let mainViewController = mainViewController {
|
||||
originalSuperview.addSubview(mainViewController.view)
|
||||
}
|
||||
|
||||
if notification.name == NSNotification.Name.UIApplicationDidEnterBackground {
|
||||
hideMenuStart().hideMenuComplete()
|
||||
menuViewController?.dismiss(animated: false, completion: nil)
|
||||
return
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: sideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
self.hideMenuStart()
|
||||
}) { (finished) -> Void in
|
||||
self.hideMenuComplete()
|
||||
self.menuViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SideMenuTransition: UIViewControllerAnimatedTransitioning {
|
||||
|
||||
// animate a change from one viewcontroller to another
|
||||
open func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
|
||||
// get reference to our fromView, toView and the container view that we should perform the transition in
|
||||
let container = transitionContext.containerView
|
||||
// prevent any other menu gestures from firing
|
||||
container.isUserInteractionEnabled = false
|
||||
|
||||
if let menuBackgroundColor = sideMenuManager.menuAnimationBackgroundColor {
|
||||
container.backgroundColor = menuBackgroundColor
|
||||
}
|
||||
|
||||
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
|
||||
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
|
||||
|
||||
// assign references to our menu view controller and the 'bottom' view controller from the tuple
|
||||
// remember that our menuViewController will alternate between the from and to view controller depending if we're presenting or dismissing
|
||||
mainViewController = presenting ? fromViewController : toViewController
|
||||
|
||||
let menuView = menuViewController!.view!
|
||||
let topView = mainViewController!.view!
|
||||
|
||||
// prepare menu items to slide in
|
||||
if presenting {
|
||||
originalSuperview = topView.superview
|
||||
|
||||
// add the both views to our view controller
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
container.addSubview(menuView)
|
||||
container.addSubview(topView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
container.addSubview(topView)
|
||||
container.addSubview(menuView)
|
||||
}
|
||||
|
||||
if sideMenuManager.menuFadeStatusBar {
|
||||
let statusBarView = UIView()
|
||||
self.statusBarView = statusBarView
|
||||
container.addSubview(statusBarView)
|
||||
}
|
||||
|
||||
hideMenuStart()
|
||||
}
|
||||
|
||||
let animate = {
|
||||
if self.presenting {
|
||||
self.presentMenuStart()
|
||||
} else {
|
||||
self.hideMenuStart()
|
||||
}
|
||||
}
|
||||
|
||||
let complete = {
|
||||
container.isUserInteractionEnabled = true
|
||||
|
||||
// tell our transitionContext object that we've finished animating
|
||||
if transitionContext.transitionWasCancelled {
|
||||
let viewControllerForPresentedMenu = self.mainViewController
|
||||
|
||||
if self.presenting {
|
||||
self.hideMenuComplete()
|
||||
} else {
|
||||
self.presentMenuComplete()
|
||||
}
|
||||
|
||||
transitionContext.completeTransition(false)
|
||||
|
||||
if self.switchMenus {
|
||||
self.switchMenus = false
|
||||
viewControllerForPresentedMenu?.present(self.menuViewController!, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if self.presenting {
|
||||
self.presentMenuComplete()
|
||||
transitionContext.completeTransition(true)
|
||||
switch self.sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
container.addSubview(topView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
container.insertSubview(topView, at: 0)
|
||||
}
|
||||
if !self.sideMenuManager.menuPresentingViewControllerUserInteractionEnabled {
|
||||
let tapView = UIView()
|
||||
container.insertSubview(tapView, aboveSubview: topView)
|
||||
tapView.bounds = container.bounds
|
||||
tapView.center = topView.center
|
||||
if self.sideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
tapView.transform = topView.transform
|
||||
}
|
||||
self.tapView = tapView
|
||||
}
|
||||
if let statusBarView = self.statusBarView {
|
||||
container.bringSubview(toFront: statusBarView)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.hideMenuComplete()
|
||||
transitionContext.completeTransition(true)
|
||||
menuView.removeFromSuperview()
|
||||
}
|
||||
|
||||
// perform the animation!
|
||||
let duration = transitionDuration(using: transitionContext)
|
||||
if interactive {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: duration, // HACK: If zero, the animation briefly flashes in iOS 11.
|
||||
options: .curveLinear,
|
||||
animations: {
|
||||
animate()
|
||||
}, completion: { (finished) in
|
||||
complete()
|
||||
})
|
||||
} else {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
animate()
|
||||
}) { (finished) -> Void in
|
||||
complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return how many seconds the transiton animation will take
|
||||
open func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||
if interactive {
|
||||
return sideMenuManager.menuAnimationCompleteGestureDuration
|
||||
}
|
||||
return presenting ? sideMenuManager.menuAnimationPresentDuration : sideMenuManager.menuAnimationDismissDuration
|
||||
}
|
||||
|
||||
open override func update(_ percentComplete: CGFloat) {
|
||||
guard !switchMenus else {
|
||||
return
|
||||
}
|
||||
|
||||
super.update(percentComplete)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SideMenuTransition: UIViewControllerTransitioningDelegate {
|
||||
|
||||
// return the animator when presenting a viewcontroller
|
||||
// rememeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
|
||||
open func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
self.presenting = true
|
||||
presentDirection = presented == sideMenuManager.menuLeftNavigationController ? .left : .right
|
||||
return self
|
||||
}
|
||||
|
||||
// return the animator used when dismissing from a viewcontroller
|
||||
open func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
presenting = false
|
||||
return self
|
||||
}
|
||||
|
||||
open func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
// if our interactive flag is true, return the transition manager object
|
||||
// otherwise return nil
|
||||
return interactive ? self : nil
|
||||
}
|
||||
|
||||
open func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
return interactive ? self : nil
|
||||
}
|
||||
|
||||
}
|
||||
343
Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift
generated
Normal file
343
Pods/SideMenu/Pod/Classes/UISideMenuNavigationController.swift
generated
Normal file
@@ -0,0 +1,343 @@
|
||||
//
|
||||
// UISideMenuNavigationController.swift
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
// Copyright © 2016 Jon Kent. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc public protocol UISideMenuNavigationControllerDelegate {
|
||||
@objc optional func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
open class UISideMenuNavigationController: UINavigationController {
|
||||
|
||||
fileprivate weak var foundDelegate: UISideMenuNavigationControllerDelegate?
|
||||
fileprivate weak var activeDelegate: UISideMenuNavigationControllerDelegate? {
|
||||
get {
|
||||
guard !view.isHidden else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sideMenuDelegate ?? foundDelegate ?? findDelegate(forViewController: presentingViewController)
|
||||
}
|
||||
}
|
||||
fileprivate func findDelegate(forViewController: UIViewController?) -> UISideMenuNavigationControllerDelegate? {
|
||||
if let navigationController = forViewController as? UINavigationController {
|
||||
return findDelegate(forViewController: navigationController.topViewController)
|
||||
}
|
||||
if let tabBarController = forViewController as? UITabBarController {
|
||||
return findDelegate(forViewController: tabBarController.selectedViewController)
|
||||
}
|
||||
if let splitViewController = forViewController as? UISplitViewController {
|
||||
return findDelegate(forViewController: splitViewController.viewControllers.last)
|
||||
}
|
||||
|
||||
foundDelegate = forViewController as? UISideMenuNavigationControllerDelegate
|
||||
return foundDelegate
|
||||
}
|
||||
fileprivate var usingInterfaceBuilder = false
|
||||
internal var locked = false
|
||||
internal var originalMenuBackgroundColor: UIColor?
|
||||
internal var transition: SideMenuTransition {
|
||||
get {
|
||||
return sideMenuManager.transition
|
||||
}
|
||||
}
|
||||
|
||||
/// Delegate for receiving appear and disappear related events. If `nil` the visible view controller that displays a `UISideMenuNavigationController` automatically receives these events.
|
||||
open weak var sideMenuDelegate: UISideMenuNavigationControllerDelegate?
|
||||
|
||||
/// SideMenuManager instance associated with this menu. Default is `SideMenuManager.default`. This property cannot be changed after the menu has loaded.
|
||||
open weak var sideMenuManager: SideMenuManager! = SideMenuManager.default {
|
||||
didSet {
|
||||
if locked && oldValue != nil {
|
||||
print("SideMenu Warning: a menu's sideMenuManager property cannot be changed after it has loaded.")
|
||||
sideMenuManager = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `sideMenuManager.menuWidth` is used. This property cannot be changed while the isHidden property is false.
|
||||
@IBInspectable open var menuWidth: CGFloat = 0 {
|
||||
didSet {
|
||||
if !isHidden && oldValue != menuWidth {
|
||||
print("SideMenu Warning: a menu's width property can only be changed when it is hidden.")
|
||||
menuWidth = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
|
||||
@IBInspectable open var leftSide: Bool = false {
|
||||
didSet {
|
||||
if locked && leftSide != oldValue {
|
||||
print("SideMenu Warning: a menu's leftSide property cannot be changed after it has loaded.")
|
||||
leftSide = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller.
|
||||
open var isHidden: Bool {
|
||||
get {
|
||||
return self.presentingViewController == nil
|
||||
}
|
||||
}
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
// This override prevents newbie developers from creating black/blank menus and opening newbie issues.
|
||||
// If you would like to remove this override, define STFU_SIDEMENU in the Active Compilation Conditions of your .plist file.
|
||||
// Sorry for the inconvenience experienced developers :(
|
||||
@available(*, unavailable, renamed: "init(rootViewController:)")
|
||||
public init() {
|
||||
fatalError("init is not available")
|
||||
}
|
||||
|
||||
public override init(rootViewController: UIViewController) {
|
||||
super.init(rootViewController: rootViewController)
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
#endif
|
||||
|
||||
open override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
usingInterfaceBuilder = true
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
if !locked && usingInterfaceBuilder {
|
||||
if leftSide {
|
||||
sideMenuManager.menuLeftNavigationController = self
|
||||
} else {
|
||||
sideMenuManager.menuRightNavigationController = self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Dismiss keyboard to prevent weird keyboard animations from occurring during transition
|
||||
presentingViewController?.view.endEditing(true)
|
||||
|
||||
foundDelegate = nil
|
||||
activeDelegate?.sideMenuWillAppear?(menu: self, animated: animated)
|
||||
}
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// We had presented a view before, so lets dismiss ourselves as already acted upon
|
||||
if view.isHidden {
|
||||
transition.hideMenuComplete()
|
||||
dismiss(animated: false, completion: { () -> Void in
|
||||
self.view.isHidden = false
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuDidAppear?(menu: self, animated: animated)
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if topViewController == nil {
|
||||
print("SideMenu Warning: the menu doesn't have a view controller to show! UISideMenuNavigationController needs a view controller to display just like a UINavigationController.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
override open func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
|
||||
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
|
||||
if !isBeingDismissed {
|
||||
guard let sideMenuManager = sideMenuManager else {
|
||||
return
|
||||
}
|
||||
|
||||
if let mainView = transition.mainViewController?.view {
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
mainView.superview?.insertSubview(view, belowSubview: mainView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
if let tapView = transition.tapView {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: tapView)
|
||||
} else {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: mainView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
|
||||
UIView.animate(withDuration: animated ? sideMenuManager.menuAnimationDismissDuration : 0,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
self.transition.hideMenuStart()
|
||||
self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
|
||||
}) { (finished) -> Void in
|
||||
self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
self.view.isHidden = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
// Work-around: if the menu is dismissed without animation the transition logic is never called to restore the
|
||||
// the view hierarchy leaving the screen black/empty. This is because the transition moves views within a container
|
||||
// view, but dismissing without animation removes the container view before the original hierarchy is restored.
|
||||
// This check corrects that.
|
||||
if let sideMenuDelegate = activeDelegate as? UIViewController, sideMenuDelegate.view.window == nil {
|
||||
transition.hideMenuStart().hideMenuComplete()
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
|
||||
// Clear selecton on UITableViewControllers when reappearing using custom transitions
|
||||
guard let tableViewController = topViewController as? UITableViewController,
|
||||
let tableView = tableViewController.tableView,
|
||||
let indexPaths = tableView.indexPathsForSelectedRows,
|
||||
tableViewController.clearsSelectionOnViewWillAppear else {
|
||||
return
|
||||
}
|
||||
|
||||
for indexPath in indexPaths {
|
||||
tableView.deselectRow(at: indexPath, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
// Don't bother resizing if the view isn't visible
|
||||
guard !view.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
NotificationCenter.default.removeObserver(self.transition, name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
coordinator.animate(alongsideTransition: { (context) in
|
||||
self.transition.presentMenuStart()
|
||||
}) { (context) in
|
||||
NotificationCenter.default.addObserver(self.transition, selector:#selector(SideMenuTransition.handleNotification), name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
|
||||
guard let sideMenuManager = sideMenuManager, viewControllers.count > 0 && sideMenuManager.menuPushStyle != .subMenu else {
|
||||
// NOTE: pushViewController is called by init(rootViewController: UIViewController)
|
||||
// so we must perform the normal super method in this case.
|
||||
super.pushViewController(viewController, animated: animated)
|
||||
return
|
||||
}
|
||||
|
||||
let splitViewController = presentingViewController as? UISplitViewController
|
||||
let tabBarController = presentingViewController as? UITabBarController
|
||||
let potentialNavigationController = (splitViewController?.viewControllers.first ?? tabBarController?.selectedViewController) ?? presentingViewController
|
||||
guard let navigationController = potentialNavigationController as? UINavigationController else {
|
||||
print("SideMenu Warning: attempt to push a View Controller from \(String(describing: potentialNavigationController.self)) where its navigationController == nil. It must be embedded in a Navigation Controller for this to work.")
|
||||
return
|
||||
}
|
||||
|
||||
let activeDelegate = self.activeDelegate
|
||||
foundDelegate = nil
|
||||
|
||||
// To avoid overlapping dismiss & pop/push calls, create a transaction block where the menu
|
||||
// is dismissed after showing the appropriate screen
|
||||
CATransaction.begin()
|
||||
if sideMenuManager.menuDismissOnPush {
|
||||
let animated = animated || sideMenuManager.menuAlwaysAnimate
|
||||
|
||||
CATransaction.setCompletionBlock( { () -> Void in
|
||||
activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
if !animated {
|
||||
self.transition.hideMenuStart().hideMenuComplete()
|
||||
}
|
||||
self.dismiss(animated: animated, completion: nil)
|
||||
})
|
||||
|
||||
if animated {
|
||||
let areAnimationsEnabled = UIView.areAnimationsEnabled
|
||||
UIView.setAnimationsEnabled(true)
|
||||
UIView.animate(withDuration: sideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
|
||||
self.transition.hideMenuStart()
|
||||
})
|
||||
UIView.setAnimationsEnabled(areAnimationsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
if let lastViewController = navigationController.viewControllers.last, !sideMenuManager.menuAllowPushOfSameClassTwice && type(of: lastViewController) == type(of: viewController) {
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
|
||||
switch sideMenuManager.menuPushStyle {
|
||||
case .subMenu, .defaultBehavior: break // .subMenu handled earlier, .defaultBehavior falls through to end
|
||||
case .popWhenPossible:
|
||||
for subViewController in navigationController.viewControllers.reversed() {
|
||||
if type(of: subViewController) == type(of: viewController) {
|
||||
navigationController.popToViewController(subViewController, animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
}
|
||||
case .preserve, .preserveAndHideBackButton:
|
||||
var viewControllers = navigationController.viewControllers
|
||||
let filtered = viewControllers.filter { preservedViewController in type(of: preservedViewController) == type(of: viewController) }
|
||||
if let preservedViewController = filtered.last {
|
||||
viewControllers = viewControllers.filter { subViewController in subViewController !== preservedViewController }
|
||||
if sideMenuManager.menuPushStyle == .preserveAndHideBackButton {
|
||||
preservedViewController.navigationItem.hidesBackButton = true
|
||||
}
|
||||
viewControllers.append(preservedViewController)
|
||||
navigationController.setViewControllers(viewControllers, animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
if sideMenuManager.menuPushStyle == .preserveAndHideBackButton {
|
||||
viewController.navigationItem.hidesBackButton = true
|
||||
}
|
||||
case .replace:
|
||||
viewController.navigationItem.hidesBackButton = true
|
||||
navigationController.setViewControllers([viewController], animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
|
||||
navigationController.pushViewController(viewController, animated: animated)
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
61
Pods/SideMenu/Pod/Classes/UITableViewVibrantCell.swift
generated
Normal file
61
Pods/SideMenu/Pod/Classes/UITableViewVibrantCell.swift
generated
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// UITableViewVibrantCell.swift
|
||||
// Pods
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
//
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class UITableViewVibrantCell: UITableViewCell {
|
||||
|
||||
fileprivate var vibrancyView:UIVisualEffectView = UIVisualEffectView()
|
||||
fileprivate var vibrancySelectedBackgroundView:UIVisualEffectView = UIVisualEffectView()
|
||||
fileprivate var defaultSelectedBackgroundView:UIView?
|
||||
open var blurEffectStyle: UIBlurEffectStyle? {
|
||||
didSet {
|
||||
updateBlur()
|
||||
}
|
||||
}
|
||||
|
||||
// For registering with UITableView without subclassing otherwise dequeuing instance of the cell causes an exception
|
||||
public override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
|
||||
vibrancyView.frame = bounds
|
||||
vibrancyView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
for view in subviews {
|
||||
vibrancyView.contentView.addSubview(view)
|
||||
}
|
||||
addSubview(vibrancyView)
|
||||
|
||||
let blurSelectionEffect = UIBlurEffect(style: .light)
|
||||
vibrancySelectedBackgroundView.effect = blurSelectionEffect
|
||||
defaultSelectedBackgroundView = selectedBackgroundView
|
||||
|
||||
updateBlur()
|
||||
}
|
||||
|
||||
internal func updateBlur() {
|
||||
// shouldn't be needed but backgroundColor is set to white on iPad:
|
||||
backgroundColor = UIColor.clear
|
||||
|
||||
if let blurEffectStyle = blurEffectStyle, !UIAccessibilityIsReduceTransparencyEnabled() {
|
||||
let blurEffect = UIBlurEffect(style: blurEffectStyle)
|
||||
vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||
|
||||
if selectedBackgroundView != nil && selectedBackgroundView != vibrancySelectedBackgroundView {
|
||||
vibrancySelectedBackgroundView.contentView.addSubview(selectedBackgroundView!)
|
||||
selectedBackgroundView = vibrancySelectedBackgroundView
|
||||
}
|
||||
} else {
|
||||
vibrancyView.effect = nil
|
||||
selectedBackgroundView = defaultSelectedBackgroundView
|
||||
}
|
||||
}
|
||||
}
|
||||
362
Pods/SideMenu/README.md
generated
Normal file
362
Pods/SideMenu/README.md
generated
Normal file
@@ -0,0 +1,362 @@
|
||||
# ▤ SideMenu
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
|
||||
### If you like SideMenu, give it a ★ at the top right of its [GitHub](https://github.com/jonkykong/SideMenu) page.
|
||||
#### Using SideMenu in your app? [Send](mailto:yo@massappeal.co?subject=SideMenu%20in%20action!) me a link to your app in the app store!
|
||||
|
||||
> Hi, I'm Jon Kent and I am an iOS designer, developer, and mobile strategist. I love coffee and play the drums.
|
||||
> * [**Hire me**](mailto:yo@massappeal.co?subject=Let's%20build%20something%20amazing) to help you make cool stuff. *Note: If you're having a problem with SideMenu, please open an [issue](https://github.com/jonkykong/SideMenu/issues/new) and do not email me.*
|
||||
> * Check out my [website](http://massappeal.co) to see some of my other projects.
|
||||
> * Building and maintaining this **free** library takes a lot of my time and **saves you time**. Please consider paying it forward by supporting me with a small amount to my [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=contact%40jonkent%2eme&lc=US¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). (only **2** people have donated since inception 😕 but **thank you** to those who have!)
|
||||
|
||||
* **[Overview](#overview)**
|
||||
* [Preview Samples](#preview-samples)
|
||||
* **[Requirements](#requirements)**
|
||||
* **[Installation](#installation)**
|
||||
* [CocoaPods](#cocoapods)
|
||||
* [Carthage](#carthage)
|
||||
* **[Usage](#usage)**
|
||||
* [Code-less Storyboard Implementation](#code-less-storyboard-implementation)
|
||||
* [Code Implementation](#code-implementation)
|
||||
* **[Customization](#customization)**
|
||||
* [SideMenuManager](#sidemenumanager)
|
||||
* [UISideMenuNavigationController](#uisidemenunavigationcontroller)
|
||||
* [UISideMenuNavigationControllerDelegate](#uisidemenunavigationcontrollerdelegate)
|
||||
* [Advanced](#advanced)
|
||||
* [Known Issues](#known-issues)
|
||||
* [Thank You](#thank-you)
|
||||
* [License](#license)
|
||||
|
||||
## Overview
|
||||
|
||||
SideMenu is a simple and versatile side menu control written in Swift.
|
||||
- [x] **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
|
||||
- [x] Four standard animation styles to choose from (there's even a parallax effect if you want to get weird).
|
||||
- [x] Highly customizable without needing to write tons of custom code.
|
||||
- [x] Supports continuous swiping between side menus on boths sides in a single gesture.
|
||||
- [x] Global menu configuration. Set-up once and be done for all screens.
|
||||
- [x] Menus can be presented and dismissed the same as any other view controller since this control uses [custom transitions](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/CustomizingtheTransitionAnimations.html).
|
||||
- [x] Animations use your view controllers, not snapshots.
|
||||
- [x] Properly handles screen rotation and in-call status bar height changes.
|
||||
|
||||
Check out the example project to see it in action!
|
||||
### Preview Samples
|
||||
| Slide Out | Slide In | Dissolve | Slide In + Out |
|
||||
| --- | --- | --- | --- |
|
||||
|  |  |  |  |
|
||||
|
||||
## Requirements
|
||||
- [x] Xcode 9.
|
||||
- [x] iOS 9 or higher.
|
||||
|
||||
## Installation
|
||||
### CocoaPods
|
||||
|
||||
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
|
||||
|
||||
```bash
|
||||
$ gem install cocoapods
|
||||
```
|
||||
|
||||
To integrate SideMenu into your Xcode project using CocoaPods, specify it in your `Podfile`:
|
||||
|
||||
```ruby
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
use_frameworks!
|
||||
|
||||
pod 'SideMenu'
|
||||
|
||||
# For Swift 3 (no longer maintained), use:
|
||||
# pod 'SideMenu', '~> 3.1.7'
|
||||
```
|
||||
|
||||
Then, run the following command:
|
||||
|
||||
```bash
|
||||
$ pod install
|
||||
```
|
||||
|
||||
### Carthage
|
||||
|
||||
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
|
||||
|
||||
You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
|
||||
|
||||
```bash
|
||||
$ brew update
|
||||
$ brew install carthage
|
||||
```
|
||||
|
||||
To integrate SideMenu into your Xcode project using Carthage, specify it in your `Cartfile`:
|
||||
|
||||
```ogdl
|
||||
github "jonkykong/SideMenu" "master"
|
||||
```
|
||||
|
||||
## Usage
|
||||
### Code-less Storyboard Implementation
|
||||
1. Create a Navigation Controller for a side menu. Set the `Custom Class` of the Navigation Controller to be `UISideMenuNavigationController` in the **Identity Inspector**. Set the `Module` to `SideMenu` (ignore this step if you've manually added SideMenu to your project). Create a Root View Controller for the Navigation Controller (shown as a UITableViewController below). Set up any Triggered Segues you want in that view controller.
|
||||

|
||||
|
||||
2. Set the `Left Side` property of the `UISideMenuNavigationController` to On if you want it to appear from the left side of the screen, or Off/Default if you want it to appear from the right side.
|
||||

|
||||
|
||||
3. Add a UIButton or UIBarButton to a view controller that you want to display the menu from. Set that button's Triggered Segues action to modally present the Navigation Controller from step 1.
|
||||

|
||||
|
||||
That's it. *Note: you can only enable gestures in code.*
|
||||
### Code Implementation
|
||||
First:
|
||||
```swift
|
||||
import SideMenu
|
||||
```
|
||||
|
||||
In your view controller's `viewDidLoad` event, do something like this (**IMPORTANT: If you're seeing a black menu when you use gestures, read this section carefully!**):
|
||||
``` swift
|
||||
// Define the menus
|
||||
let menuLeftNavigationController = UISideMenuNavigationController(rootViewController: YourViewController)
|
||||
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
|
||||
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
|
||||
// let menuLeftNavigationController = storyboard!.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as! UISideMenuNavigationController
|
||||
SideMenuManager.default.menuLeftNavigationController = menuLeftNavigationController
|
||||
|
||||
let menuRightNavigationController = UISideMenuNavigationController(rootViewController: YourViewController)
|
||||
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
|
||||
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
|
||||
// let menuRightNavigationController = storyboard!.instantiateViewController(withIdentifier: "RightMenuNavigationController") as! UISideMenuNavigationController
|
||||
SideMenuManager.default.menuRightNavigationController = menuRightNavigationController
|
||||
|
||||
// Enable gestures. The left and/or right menus must be set up above for these to work.
|
||||
// Note that these continue to work on the Navigation Controller independent of the view controller it displays!
|
||||
SideMenuManager.default.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
```
|
||||
Then from a button, do something like this:
|
||||
``` swift
|
||||
present(SideMenuManager.default.menuLeftNavigationController!, animated: true, completion: nil)
|
||||
|
||||
// Similarly, to dismiss a menu programmatically, you would do this:
|
||||
dismiss(animated: true, completion: nil)
|
||||
```
|
||||
That's it.
|
||||
### Customization
|
||||
#### SideMenuManager
|
||||
Just type ` SideMenuManager.default.menu...` and code completion will show you everything you can customize (for Objective-C, use `SideMenuManager.defaultManager.menu...`). Defaults values are shown below for reference:
|
||||
``` swift
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved.
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
open var menuPushStyle: MenuPushStyle = .defaultBehavior
|
||||
|
||||
/**
|
||||
The presentation mode of the menu.
|
||||
|
||||
There are four modes in MenuPresentMode:
|
||||
- menuSlideIn: Menu slides in over of the existing view.
|
||||
- viewSlideOut: The existing view slides out to reveal the menu.
|
||||
- viewSlideInOut: The existing view slides out while the menu slides in.
|
||||
- menuDissolveIn: The menu dissolves in over the existing view controller.
|
||||
*/
|
||||
open var menuPresentMode: MenuPresentMode = .viewSlideOut
|
||||
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
open var menuAllowPushOfSameClassTwice = true
|
||||
|
||||
/**
|
||||
Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width.
|
||||
|
||||
Note that each menu's width can be overridden using the `menuWidth` property on any `UISideMenuNavigationController` instance.
|
||||
*/
|
||||
open var menuWidth: CGFloat = max(round(min((appScreenRect.width), (appScreenRect.height)) * 0.75), 240)
|
||||
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationPresentDuration: Double = 0.35
|
||||
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationDismissDuration: Double = 0.35
|
||||
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationCompleteGestureDuration: Double = 0.35
|
||||
|
||||
/// Amount to fade the existing view controller when the menu is presented. Default is 0 for no fade. Set to 1 to fade completely.
|
||||
open var menuAnimationFadeStrength: CGFloat = 0
|
||||
|
||||
/// The amount to scale the existing view controller or the menu view controller depending on the `menuPresentMode`. Default is 1 for no scaling. Less than 1 will shrink, greater than 1 will grow.
|
||||
open var menuAnimationTransformScaleFactor: CGFloat = 1
|
||||
|
||||
/// The background color behind menu animations. Depending on the animation settings this may not be visible. If `menuFadeStatusBar` is true, this color is used to fade it. Default is black.
|
||||
open var menuAnimationBackgroundColor: UIColor?
|
||||
|
||||
/// The shadow opacity around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 0.5 for 50% opacity.
|
||||
open var menuShadowOpacity: Float = 0.5
|
||||
|
||||
/// The shadow color around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is black.
|
||||
open var menuShadowColor = UIColor.black
|
||||
|
||||
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
|
||||
open var menuShadowRadius: CGFloat = 5
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
|
||||
open var menuEnableSwipeGestures: Bool = true
|
||||
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. Default is false.
|
||||
open var menuPresentingViewControllerUserInteractionEnabled: Bool = false
|
||||
|
||||
/// The strength of the parallax effect on the existing view controller. Does not apply to `menuPresentMode` when set to `ViewSlideOut`. Default is 0.
|
||||
open var menuParallaxStrength: Int = 0
|
||||
|
||||
/// Draws the `menuAnimationBackgroundColor` behind the status bar. Default is true.
|
||||
open var menuFadeStatusBar = true
|
||||
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationOptions: UIViewAnimationOptions = .curveEaseInOut
|
||||
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationUsingSpringWithDamping: CGFloat = 1
|
||||
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open var menuDismissOnPush = true
|
||||
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
open var menuAlwaysAnimate = false
|
||||
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell and set the `blurEffectStyle` of each cell to SideMenuManager.default.menuBlurEffectStyle.
|
||||
*/
|
||||
open var menuBlurEffectStyle: UIBlurEffectStyle?
|
||||
|
||||
/// The left menu.
|
||||
open var menuLeftNavigationController: UISideMenuNavigationController?
|
||||
|
||||
/// The right menu.
|
||||
open var menuRightNavigationController: UISideMenuNavigationController?
|
||||
|
||||
/**
|
||||
Adds screen edge gestures to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add gestures to.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for. If unspecified, gestures will be added for both sides.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer]
|
||||
|
||||
/**
|
||||
Adds a pan edge gesture to a view to present menus.
|
||||
|
||||
- Parameter toView: The view to add a pan gesture to.
|
||||
|
||||
- Returns: The pan gesture added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer
|
||||
```
|
||||
#### UISideMenuNavigationController
|
||||
`UISideMenuNavigationController` supports the following customizations and properties:
|
||||
``` swift
|
||||
/// SideMenuManager instance associated with this menu. Default is `SideMenuManager.default`. This property cannot be changed after the menu has loaded.
|
||||
open weak var sideMenuManager: SideMenuManager! = SideMenuManager.default
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `sideMenuManager.menuWidth` is used. This property cannot be changed while the isHidden property is false.
|
||||
@IBInspectable open var menuWidth: CGFloat = 0
|
||||
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
|
||||
@IBInspectable open var leftSide: Bool = false
|
||||
|
||||
/// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller.
|
||||
open var isHidden: Bool
|
||||
```
|
||||
#### UISideMenuNavigationControllerDelegate
|
||||
To receive notifications when a menu is displayed from a view controller, have it adhere to the `UISideMenuNavigationControllerDelegate` protocol:
|
||||
``` swift
|
||||
extension MyViewController: UISideMenuNavigationControllerDelegate {
|
||||
|
||||
func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
*Note: setting the `sideMenuDelegate` property on `UISideMenuNavigationController` is optional. If your view controller adheres to the protocol then the methods will be called automatically.*
|
||||
### Advanced
|
||||
For simplicity, `SideMenuManager.default` serves as the primary instance as most projects will only need one menu across all screens. If you need to show a different SideMenu, such as from a modal view controller presented from a previous SideMenu, do the following:
|
||||
1. Declare a variable containing your custom `SideMenuManager` instance. You may want it to define it globally and configure it in your app delegate if menus will be used on multiple screens.
|
||||
``` swift
|
||||
let customSideMenuManager = SideMenuManager()
|
||||
```
|
||||
2. Setup and display menus with your custom instance the same as you would with the `SideMenuManager.default` instance.
|
||||
3. If using Storyboards, subclass your instance of `UISideMenuNavigationController` and set its `sideMenuManager` property to your custom instance. This must be done before `viewDidLoad` is called:
|
||||
``` swift
|
||||
class MySideMenuNavigationController: UISideMenuNavigationController {
|
||||
|
||||
let customSideMenuManager = SideMenuManager()
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
sideMenuManager = customSideMenuManager
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
Alternatively, you can set `sideMenuManager` from the view controller that segues to your UISideMenuNavigationController:
|
||||
``` swift
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if let sideMenuNavigationController = segue.destination as? UISideMenuNavigationController {
|
||||
sideMenuNavigationController.sideMenuManager = customSideMenuManager
|
||||
}
|
||||
}
|
||||
```
|
||||
*Important: displaying SideMenu instances directly over each other is not supported. Use `menuPushStyle = .subMenu` instead.*
|
||||
## Known Issues
|
||||
* Issue [#258](https://github.com/jonkykong/SideMenu/issues/258).
|
||||
* Don't try to change the status bar appearance when presenting a menu. When used with quick gestures/animations, it causes the presentation animation to not complete properly and locks the UI. This was fixed in iOS 9.3. See [radar 21961293](http://www.openradar.me/21961293) for more information.
|
||||
|
||||
## Thank You
|
||||
A special thank you to everyone that has [contributed](https://github.com/jonkykong/SideMenu/graphs/contributors) to this library to make it better. Your support is appreciated!
|
||||
|
||||
## License
|
||||
|
||||
SideMenu is available under the MIT license. See the LICENSE file for more info.
|
||||
@@ -1670,6 +1670,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
## SideMenu
|
||||
|
||||
Copyright (c) 2015 Jonathan Kent <contact@jonkent.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
## SwiftChart
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -1771,6 +1771,35 @@ SOFTWARE.
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2015 Jonathan Kent <contact@jonkent.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>MIT</string>
|
||||
<key>Title</key>
|
||||
<string>SideMenu</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>The MIT License (MIT)
|
||||
|
||||
@@ -152,6 +152,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SwiftChart/SwiftChart.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework"
|
||||
@@ -167,6 +168,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SwiftChart/SwiftChart.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebaseInstanceID/Frameworks"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebaseInstanceID/Frameworks"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit/PromiseKit.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart/SwiftChart.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "Alamofire" -framework "CFNetwork" -framework "ChameleonFramework" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstanceID" -framework "FirebaseNanoPB" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleToolboxForMac" -framework "Kingfisher" -framework "PromiseKit" -framework "Realm" -framework "RealmSwift" -framework "SVProgressHUD" -framework "Security" -framework "StoreKit" -framework "SwiftChart" -framework "SwiftyJSON" -framework "SystemConfiguration" -framework "leveldb" -framework "nanopb"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit/PromiseKit.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu/SideMenu.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart/SwiftChart.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "Alamofire" -framework "CFNetwork" -framework "ChameleonFramework" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstanceID" -framework "FirebaseNanoPB" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleToolboxForMac" -framework "Kingfisher" -framework "PromiseKit" -framework "Realm" -framework "RealmSwift" -framework "SVProgressHUD" -framework "Security" -framework "SideMenu" -framework "StoreKit" -framework "SwiftChart" -framework "SwiftyJSON" -framework "SystemConfiguration" -framework "leveldb" -framework "nanopb"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebaseInstanceID/Frameworks"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebaseInstanceID/Frameworks"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit/PromiseKit.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart/SwiftChart.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "Alamofire" -framework "CFNetwork" -framework "ChameleonFramework" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstanceID" -framework "FirebaseNanoPB" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleToolboxForMac" -framework "Kingfisher" -framework "PromiseKit" -framework "Realm" -framework "RealmSwift" -framework "SVProgressHUD" -framework "Security" -framework "StoreKit" -framework "SwiftChart" -framework "SwiftyJSON" -framework "SystemConfiguration" -framework "leveldb" -framework "nanopb"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PromiseKit/PromiseKit.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu/SideMenu.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftChart/SwiftChart.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Firebase"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "Alamofire" -framework "CFNetwork" -framework "ChameleonFramework" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstanceID" -framework "FirebaseNanoPB" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleToolboxForMac" -framework "Kingfisher" -framework "PromiseKit" -framework "Realm" -framework "RealmSwift" -framework "SVProgressHUD" -framework "Security" -framework "SideMenu" -framework "StoreKit" -framework "SwiftChart" -framework "SwiftyJSON" -framework "SystemConfiguration" -framework "leveldb" -framework "nanopb"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
26
Pods/Target Support Files/SideMenu/Info.plist
generated
Normal file
26
Pods/Target Support Files/SideMenu/Info.plist
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
5
Pods/Target Support Files/SideMenu/SideMenu-dummy.m
generated
Normal file
5
Pods/Target Support Files/SideMenu/SideMenu-dummy.m
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_SideMenu : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_SideMenu
|
||||
@end
|
||||
12
Pods/Target Support Files/SideMenu/SideMenu-prefix.pch
generated
Normal file
12
Pods/Target Support Files/SideMenu/SideMenu-prefix.pch
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
16
Pods/Target Support Files/SideMenu/SideMenu-umbrella.h
generated
Normal file
16
Pods/Target Support Files/SideMenu/SideMenu-umbrella.h
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
FOUNDATION_EXPORT double SideMenuVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char SideMenuVersionString[];
|
||||
|
||||
6
Pods/Target Support Files/SideMenu/SideMenu.modulemap
generated
Normal file
6
Pods/Target Support Files/SideMenu/SideMenu.modulemap
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
framework module SideMenu {
|
||||
umbrella header "SideMenu-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
9
Pods/Target Support Files/SideMenu/SideMenu.xcconfig
generated
Normal file
9
Pods/Target Support Files/SideMenu/SideMenu.xcconfig
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SideMenu
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/SideMenu
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
@@ -32,10 +32,17 @@
|
||||
C58C142C20B87197001BE9DA /* ChannelHistoryValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C58C142B20B87197001BE9DA /* ChannelHistoryValue.swift */; };
|
||||
C58C142E20BDD6BA001BE9DA /* HistoryGraphViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C58C142D20BDD6BA001BE9DA /* HistoryGraphViewController.swift */; };
|
||||
C5AA264A20C1BED600B39425 /* AppAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5AA264920C1BED600B39425 /* AppAuth.swift */; };
|
||||
C5B75C1F20BE339F00EB850D /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B75C1E20BE339F00EB850D /* NavigationController.swift */; };
|
||||
C5B75C2120BE350600EB850D /* MeshifyFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B75C2020BE350600EB850D /* MeshifyFunctions.swift */; };
|
||||
C5B75C2320BEFE3500EB850D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C5B75C2220BEFE3500EB850D /* GoogleService-Info.plist */; };
|
||||
C5B75C4920C0BD8900EB850D /* MeshifyValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B75C4820C0BD8900EB850D /* MeshifyValue.swift */; };
|
||||
C5D24FD120C869F400262BE8 /* AdminViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FD020C869F400262BE8 /* AdminViewController.swift */; };
|
||||
C5D24FD320C86A6000262BE8 /* PillUILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FD220C86A6000262BE8 /* PillUILabel.swift */; };
|
||||
C5D24FD520C86CD900262BE8 /* AdminCompanyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FD420C86CD900262BE8 /* AdminCompanyCell.swift */; };
|
||||
C5D24FD720C86DBB00262BE8 /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FD620C86DBB00262BE8 /* Company.swift */; };
|
||||
C5D24FD920C87DBA00262BE8 /* NavigationMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FD820C87DBA00262BE8 /* NavigationMenuController.swift */; };
|
||||
C5D24FDB20C88C3E00262BE8 /* MainNavController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FDA20C88C3E00262BE8 /* MainNavController.swift */; };
|
||||
C5D24FDD20C891B600262BE8 /* CompanyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FDC20C891B600262BE8 /* CompanyViewController.swift */; };
|
||||
C5D24FDF20C895C500262BE8 /* Migrations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D24FDE20C895C500262BE8 /* Migrations.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -67,10 +74,17 @@
|
||||
C58C142B20B87197001BE9DA /* ChannelHistoryValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelHistoryValue.swift; sourceTree = "<group>"; };
|
||||
C58C142D20BDD6BA001BE9DA /* HistoryGraphViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryGraphViewController.swift; sourceTree = "<group>"; };
|
||||
C5AA264920C1BED600B39425 /* AppAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAuth.swift; sourceTree = "<group>"; };
|
||||
C5B75C1E20BE339F00EB850D /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
|
||||
C5B75C2020BE350600EB850D /* MeshifyFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshifyFunctions.swift; sourceTree = "<group>"; };
|
||||
C5B75C2220BEFE3500EB850D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
C5B75C4820C0BD8900EB850D /* MeshifyValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshifyValue.swift; sourceTree = "<group>"; };
|
||||
C5D24FD020C869F400262BE8 /* AdminViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminViewController.swift; sourceTree = "<group>"; };
|
||||
C5D24FD220C86A6000262BE8 /* PillUILabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillUILabel.swift; sourceTree = "<group>"; };
|
||||
C5D24FD420C86CD900262BE8 /* AdminCompanyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminCompanyCell.swift; sourceTree = "<group>"; };
|
||||
C5D24FD620C86DBB00262BE8 /* Company.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = "<group>"; };
|
||||
C5D24FD820C87DBA00262BE8 /* NavigationMenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenuController.swift; sourceTree = "<group>"; };
|
||||
C5D24FDA20C88C3E00262BE8 /* MainNavController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavController.swift; sourceTree = "<group>"; };
|
||||
C5D24FDC20C891B600262BE8 /* CompanyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyViewController.swift; sourceTree = "<group>"; };
|
||||
C5D24FDE20C895C500262BE8 /* Migrations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Migrations.swift; sourceTree = "<group>"; };
|
||||
D7E8B9ABE8755B533A815A1B /* Pods_pocloud.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_pocloud.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -101,6 +115,7 @@
|
||||
C53407E520B753940016CFAB /* DeviceDetailChannelCell.swift */,
|
||||
C53407E920B85C3F0016CFAB /* MapDetailDeviceCell.swift */,
|
||||
C53407EB20B86AE90016CFAB /* ChannelHistoryCell.swift */,
|
||||
C5D24FD420C86CD900262BE8 /* AdminCompanyCell.swift */,
|
||||
);
|
||||
path = Cells;
|
||||
sourceTree = "<group>";
|
||||
@@ -151,6 +166,8 @@
|
||||
C53407E720B76B7C0016CFAB /* GatewayAnnotation.swift */,
|
||||
C58C142B20B87197001BE9DA /* ChannelHistoryValue.swift */,
|
||||
C5B75C4820C0BD8900EB850D /* MeshifyValue.swift */,
|
||||
C5D24FD620C86DBB00262BE8 /* Company.swift */,
|
||||
C5D24FDE20C895C500262BE8 /* Migrations.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@@ -159,6 +176,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C5589BF120B47E2100639393 /* Main.storyboard */,
|
||||
C5D24FD220C86A6000262BE8 /* PillUILabel.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@@ -168,7 +186,8 @@
|
||||
children = (
|
||||
C5589BED20B47E2100639393 /* AppDelegate.swift */,
|
||||
C5B75C2020BE350600EB850D /* MeshifyFunctions.swift */,
|
||||
C5B75C1E20BE339F00EB850D /* NavigationController.swift */,
|
||||
C5D24FDA20C88C3E00262BE8 /* MainNavController.swift */,
|
||||
C5D24FD820C87DBA00262BE8 /* NavigationMenuController.swift */,
|
||||
C5589BEF20B47E2100639393 /* LoginViewController.swift */,
|
||||
C5589C7320B657CA00639393 /* DeviceListViewController.swift */,
|
||||
C5589C0B20B4B12100639393 /* MapViewController.swift */,
|
||||
@@ -176,6 +195,8 @@
|
||||
C53407DF20B7462C0016CFAB /* DeviceDetailViewController.swift */,
|
||||
C58C142920B86C1C001BE9DA /* ChannelDetailViewController.swift */,
|
||||
C58C142D20BDD6BA001BE9DA /* HistoryGraphViewController.swift */,
|
||||
C5D24FD020C869F400262BE8 /* AdminViewController.swift */,
|
||||
C5D24FDC20C891B600262BE8 /* CompanyViewController.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@@ -301,6 +322,7 @@
|
||||
"${BUILT_PRODUCTS_DIR}/Realm/Realm.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftChart/SwiftChart.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework",
|
||||
@@ -317,6 +339,7 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmSwift.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SVProgressHUD.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SideMenu.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftChart.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework",
|
||||
@@ -342,12 +365,18 @@
|
||||
C58C142E20BDD6BA001BE9DA /* HistoryGraphViewController.swift in Sources */,
|
||||
C5589C7420B657CA00639393 /* DeviceListViewController.swift in Sources */,
|
||||
C53407EA20B85C3F0016CFAB /* MapDetailDeviceCell.swift in Sources */,
|
||||
C5D24FD520C86CD900262BE8 /* AdminCompanyCell.swift in Sources */,
|
||||
C5589BEE20B47E2100639393 /* AppDelegate.swift in Sources */,
|
||||
C5D24FD920C87DBA00262BE8 /* NavigationMenuController.swift in Sources */,
|
||||
C5AA264A20C1BED600B39425 /* AppAuth.swift in Sources */,
|
||||
C5D24FDF20C895C500262BE8 /* Migrations.swift in Sources */,
|
||||
C5D24FD720C86DBB00262BE8 /* Company.swift in Sources */,
|
||||
C53407E820B76B7C0016CFAB /* GatewayAnnotation.swift in Sources */,
|
||||
C5D24FDD20C891B600262BE8 /* CompanyViewController.swift in Sources */,
|
||||
C53407E420B74B6F0016CFAB /* ChanValue.swift in Sources */,
|
||||
C53407D820B72AE80016CFAB /* Gateway.swift in Sources */,
|
||||
C5589C0420B4AA9600639393 /* User.swift in Sources */,
|
||||
C5D24FDB20C88C3E00262BE8 /* MainNavController.swift in Sources */,
|
||||
C58C142C20B87197001BE9DA /* ChannelHistoryValue.swift in Sources */,
|
||||
C53407EC20B86AE90016CFAB /* ChannelHistoryCell.swift in Sources */,
|
||||
C5589C0C20B4B12100639393 /* MapViewController.swift in Sources */,
|
||||
@@ -355,9 +384,10 @@
|
||||
C5589C1A20B4DF0A00639393 /* MapDetailViewController.swift in Sources */,
|
||||
C53407E620B753940016CFAB /* DeviceDetailChannelCell.swift in Sources */,
|
||||
C53407DA20B7328C0016CFAB /* DeviceType.swift in Sources */,
|
||||
C5B75C1F20BE339F00EB850D /* NavigationController.swift in Sources */,
|
||||
C5B75C4920C0BD8900EB850D /* MeshifyValue.swift in Sources */,
|
||||
C5D24FD120C869F400262BE8 /* AdminViewController.swift in Sources */,
|
||||
C58C142A20B86C1C001BE9DA /* ChannelDetailViewController.swift in Sources */,
|
||||
C5D24FD320C86A6000262BE8 /* PillUILabel.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
27
pocloud/Cells/AdminCompanyCell.swift
Normal file
27
pocloud/Cells/AdminCompanyCell.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// AdminCompanyCell.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class AdminCompanyCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var companyNameLabel: UILabel!
|
||||
@IBOutlet weak var companyCountLabel: PillUILabel!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
}
|
||||
93
pocloud/Controller/AdminViewController.swift
Normal file
93
pocloud/Controller/AdminViewController.swift
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// AdminViewController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RealmSwift
|
||||
import PromiseKit
|
||||
|
||||
class AdminViewController: UITableViewController {
|
||||
let realm = try! Realm()
|
||||
let baseURL = (UIApplication.shared.delegate as! AppDelegate).baseURL
|
||||
let user = (UIApplication.shared.delegate as! AppDelegate).user
|
||||
let appAuth = AppAuth()
|
||||
|
||||
var companiesWithGateways : Results<Company>?
|
||||
var companiesNoGateways : Results<Company>?
|
||||
|
||||
var selectedCompany : Company?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Get company data from Realm
|
||||
companiesWithGateways = realm.objects(Company.self).filter("gateways.@count > 0")
|
||||
companiesNoGateways = realm.objects(Company.self).filter("gateways.@count == 0")
|
||||
|
||||
if (companiesWithGateways!.count + companiesNoGateways!.count) == 0{
|
||||
firstly {
|
||||
getAllMeshifyData(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.done {
|
||||
self.tableView.reloadData()
|
||||
}.catch { error in
|
||||
print("Error getting all meshify data in AdminViewController: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if section == 0 {
|
||||
return companiesWithGateways?.count ?? 0
|
||||
} else {
|
||||
return companiesNoGateways?.count ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if section == 0 {
|
||||
return "Companies with Devices"
|
||||
} else {
|
||||
return "Companies with NO Devices"
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "companyCell", for: indexPath) as! AdminCompanyCell
|
||||
if indexPath.section == 0 {
|
||||
cell.companyNameLabel.text = companiesWithGateways![indexPath.row].name
|
||||
cell.companyCountLabel.text = String(companiesWithGateways![indexPath.row].gateways.count)
|
||||
} else {
|
||||
cell.companyNameLabel.text = companiesNoGateways![indexPath.row].name
|
||||
cell.companyCountLabel.isHidden = true
|
||||
cell.accessoryType = .none
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if indexPath.section == 0 {
|
||||
selectedCompany = companiesWithGateways![indexPath.row]
|
||||
performSegue(withIdentifier: "openCompanyDetailView", sender: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if segue.identifier == "openCompanyDetailView" {
|
||||
let targetVC = segue.destination as! CompanyViewController
|
||||
targetVC.thisCompany = selectedCompany
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
// Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.flatSkyBlue(), with: UIContentStyle.contrast)
|
||||
// print(Realm.Configuration.defaultConfiguration.fileURL)
|
||||
Migrations().checkSchema()
|
||||
FirebaseApp.configure()
|
||||
|
||||
return true
|
||||
|
||||
102
pocloud/Controller/CompanyViewController.swift
Normal file
102
pocloud/Controller/CompanyViewController.swift
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// CompanyViewController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MapKit
|
||||
|
||||
class CompanyViewController: UIViewController, MKMapViewDelegate, UITableViewDataSource, UITableViewDelegate {
|
||||
|
||||
@IBOutlet weak var mapView: MKMapView!
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
var thisCompany : Company?
|
||||
var selectedGateway : Gateway?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
mapView.delegate = self
|
||||
|
||||
title = thisCompany?.name
|
||||
|
||||
addMapDot()
|
||||
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if let company = thisCompany{
|
||||
return company.gateways.count
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "companyGatewayCell", for: indexPath)
|
||||
cell.textLabel?.text = thisCompany?.gateways[indexPath.row].name
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
|
||||
func addMapDot(){
|
||||
let coord = CLLocationCoordinate2D(latitude: (thisCompany?.address!.lat)!, longitude: (thisCompany?.address!.long)!)
|
||||
let gatewayAnnotation = GatewayAnnotation(coordinate: coord, title: (thisCompany?.name)!, subtitle: (thisCompany?.address?.streetAddress)!, gateway: nil)
|
||||
mapView.addAnnotation(gatewayAnnotation)
|
||||
let regionRadius: CLLocationDistance = 1000
|
||||
let coordinateRegion = MKCoordinateRegionMakeWithDistance(coord, regionRadius, regionRadius)
|
||||
mapView.setRegion(coordinateRegion, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||
let identifier = "marker"
|
||||
|
||||
if annotation.isKind(of: GatewayAnnotation.self) {
|
||||
var view: MKMarkerAnnotationView
|
||||
|
||||
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
|
||||
dequeuedView.annotation = annotation
|
||||
view = dequeuedView
|
||||
} else {
|
||||
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
||||
view.canShowCallout = true
|
||||
view.calloutOffset = CGPoint(x: -5, y: 5)
|
||||
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
|
||||
}
|
||||
return view
|
||||
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
selectedGateway = thisCompany?.gateways[indexPath.row]
|
||||
performSegue(withIdentifier: "openGatewayDetail", sender: self)
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
|
||||
let location = view.annotation as! GatewayAnnotation
|
||||
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
|
||||
location.mapItem().openInMaps(launchOptions: launchOptions)
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if segue.identifier == "openGatewayDetail" {
|
||||
let destinationVC = segue.destination as! MapDetailViewController
|
||||
destinationVC.gateway = selectedGateway
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import RealmSwift
|
||||
import SwiftyJSON
|
||||
import SVProgressHUD
|
||||
import FirebaseDatabase
|
||||
import ChameleonFramework
|
||||
|
||||
class DeviceDetailViewController: UITableViewController {
|
||||
let realm = try! Realm()
|
||||
@@ -28,6 +29,7 @@ class DeviceDetailViewController: UITableViewController {
|
||||
var values : [String : MeshifyValue] = [:]
|
||||
var updatedChannelNames : [String] = [String]()
|
||||
var changedChannelNames : [String] = [String]()
|
||||
let numFormatter = NumberFormatter()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@@ -35,6 +37,10 @@ class DeviceDetailViewController: UITableViewController {
|
||||
let macAddress = String((thisDevice?.macAddress.replacingOccurrences(of: ":", with: "").uppercased().dropLast(4))!)
|
||||
let deviceTypeName = (thisDevice?.parentDeviceType.first?.name)!
|
||||
|
||||
numFormatter.minimumFractionDigits = 0
|
||||
numFormatter.maximumFractionDigits = 3
|
||||
numFormatter.minimumIntegerDigits = 1
|
||||
|
||||
SVProgressHUD.show()
|
||||
firstly {
|
||||
loadData()
|
||||
@@ -138,6 +144,18 @@ class DeviceDetailViewController: UITableViewController {
|
||||
print("Error fetching data in DeviceDetailViewController: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func tryRound(value : String, places numberOfPlaces: Int) -> String {
|
||||
if let doubledValue = Double(value) {
|
||||
if let formattedString = numFormatter.string(from: NSNumber(value: doubledValue)) {
|
||||
return formattedString
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -158,6 +176,7 @@ class DeviceDetailViewController: UITableViewController {
|
||||
let chanName = thisDevice?.parentDeviceType.first?.channels[indexPath.row].name
|
||||
let chanVal = values[chanName!]
|
||||
|
||||
|
||||
if let i = changedChannelNames.index(of: chanName!) {
|
||||
changedChannelNames.remove(at: i)
|
||||
cell.backgroundColor = UIColor.flatLime()
|
||||
@@ -180,8 +199,8 @@ class DeviceDetailViewController: UITableViewController {
|
||||
}
|
||||
}
|
||||
|
||||
cell.channelValueLabel?.text = tryRound(value: chanVal!.value, places: 3)
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
cell.channelValueLabel?.text = chanVal?.value
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import SVProgressHUD
|
||||
import FirebaseAuth
|
||||
|
||||
class DeviceListViewController: UITableViewController {
|
||||
@IBOutlet weak var searchBar: UISearchBar!
|
||||
let realm = try! Realm()
|
||||
|
||||
let user = (UIApplication.shared.delegate as! AppDelegate).user
|
||||
@@ -37,6 +38,8 @@ class DeviceListViewController: UITableViewController {
|
||||
refreshControl?.attributedTitle = NSAttributedString(string: "Pull to refresh")
|
||||
refreshControl?.addTarget(self, action: #selector(refresh), for: UIControlEvents.valueChanged)
|
||||
|
||||
searchBar.delegate = self
|
||||
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Log Out", style: .plain, target: self, action: #selector(self.logOut))
|
||||
|
||||
SVProgressHUD.show()
|
||||
@@ -60,13 +63,15 @@ class DeviceListViewController: UITableViewController {
|
||||
func loadJSONData() -> Promise<Void>{
|
||||
return Promise { promise in
|
||||
firstly {
|
||||
getDeviceTypes(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
getDeviceTypes(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.then { _ in
|
||||
getAddresses(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
getCompanies(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.then { _ in
|
||||
getAddresses(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.then { _ in
|
||||
getGateways(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
getGateways(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.then { _ in
|
||||
getDevices(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
getDevices(baseURL: self.baseURL, authToken: self.user!.authToken)
|
||||
}.done{ _ in
|
||||
promise.fulfill(())
|
||||
}.catch { error in
|
||||
@@ -150,3 +155,29 @@ class DeviceListViewController: UITableViewController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DeviceListViewController : UISearchBarDelegate {
|
||||
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
|
||||
devices = devices?.filter("vanityName CONTAINS[cd] %@", searchBar.text!).sorted(byKeyPath: "vanityName", ascending: true)
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
|
||||
if searchBar.text?.count == 0 {
|
||||
firstly {
|
||||
self.loadRealmData()
|
||||
}.then{ _ in
|
||||
self.loadJSONData()
|
||||
}.done { _ in
|
||||
self.tableView.reloadData()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
searchBar.resignFirstResponder()
|
||||
}
|
||||
}.catch { error in
|
||||
print("Error in getting data in DeviceListViewController: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
35
pocloud/Controller/MainNavController.swift
Normal file
35
pocloud/Controller/MainNavController.swift
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// MainNavController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MainNavController: UINavigationController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// MARK: - Navigation
|
||||
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
// Get the new view controller using segue.destinationViewController.
|
||||
// Pass the selected object to the new view controller.
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -56,7 +56,8 @@ class MapViewController: UIViewController, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
let buttonItem = MKUserTrackingBarButtonItem(mapView: mapView)
|
||||
self.navigationItem.rightBarButtonItem = buttonItem
|
||||
self.navigationItem.rightBarButtonItems?.append(buttonItem)
|
||||
// self.navigationItem.rightBarButtonItem = buttonItem
|
||||
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Log Out", style: .plain, target: self, action: #selector(self.logOut))
|
||||
|
||||
|
||||
@@ -129,9 +129,11 @@ func getGateways(baseURL : String, authToken : String) -> Promise<Any> {
|
||||
gtw.userId = json["userId"].intValue
|
||||
|
||||
let associatedAddress = realm.objects(Address.self).filter("id == %d", gtw.addressId).first
|
||||
let parentCompany = realm.objects(Company.self).filter("id == %d", gtw.companyId).first
|
||||
|
||||
gtw.address = associatedAddress
|
||||
realm.add(gtw, update: true)
|
||||
parentCompany?.gateways.append(gtw)
|
||||
}
|
||||
} catch {
|
||||
seal.reject(error)
|
||||
@@ -262,20 +264,6 @@ func getChannelValues(deviceId: Int, baseURL : String, authToken : String) -> Pr
|
||||
let channelValJSON : JSON = JSON(response.result.value!)
|
||||
var valueDict : [String : MeshifyValue] = [:]
|
||||
for(chName, json) : (String, JSON) in channelValJSON {
|
||||
// do {
|
||||
// try realm.write {
|
||||
// let chv = ChanValue()
|
||||
// chv.uid = "\(deviceId).\(chName)"
|
||||
// chv.name = chName
|
||||
// chv.value = json["value"].stringValue
|
||||
// chv.timestamp = json["timestamp"].intValue
|
||||
//
|
||||
// realm.add(chv, update: true)
|
||||
// realm.objects(Device.self).filter("id == %d", deviceId).first?.values.append(chv)
|
||||
// }
|
||||
// } catch {
|
||||
// prom.reject(error)
|
||||
// }
|
||||
let chv = MeshifyValue()
|
||||
chv.name = chName
|
||||
chv.value = json["value"].stringValue
|
||||
@@ -320,6 +308,69 @@ func getChannelHistory(deviceId: Int, channelId : Int, baseURL : String, authTok
|
||||
}
|
||||
}
|
||||
|
||||
func getCompanies(baseURL : String, authToken : String) -> Promise<Any> {
|
||||
let realm = try! Realm()
|
||||
let url = "\(baseURL)/companies"
|
||||
let headers : HTTPHeaders = [
|
||||
"Authorization": authToken
|
||||
]
|
||||
|
||||
return Promise { seal in
|
||||
Alamofire.request(url, method: .get, headers: headers)
|
||||
.responseJSON { response in
|
||||
switch response.result {
|
||||
|
||||
case .success:
|
||||
let gatewaysJSON : JSON = JSON(response.result.value!)
|
||||
for(_, json) : (String, JSON) in gatewaysJSON {
|
||||
|
||||
do {
|
||||
try realm.write {
|
||||
let company = Company()
|
||||
company.id = json["id"].intValue
|
||||
company.name = json["name"].stringValue
|
||||
company.tenantId = json["tenantId"].intValue
|
||||
company.addressId = json["addressId"].intValue
|
||||
company.address = realm.objects(Address.self).filter("id == %d", company.addressId).first
|
||||
realm.add(company, update: true)
|
||||
}
|
||||
} catch {
|
||||
seal.reject(error)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
seal.fulfill(true)
|
||||
case .failure(let error):
|
||||
seal.reject(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getAllMeshifyData(baseURL : String, authToken : String) -> Promise<Void>{
|
||||
return Promise { promise in
|
||||
firstly {
|
||||
getDeviceTypes(baseURL: baseURL, authToken: authToken)
|
||||
}.then { _ in
|
||||
getCompanies(baseURL: baseURL, authToken: authToken)
|
||||
}.then { _ in
|
||||
getAddresses(baseURL: baseURL, authToken: authToken)
|
||||
}.then { _ in
|
||||
getGateways(baseURL: baseURL, authToken: authToken)
|
||||
}.then { _ in
|
||||
getDevices(baseURL: baseURL, authToken: authToken)
|
||||
}.done{ _ in
|
||||
promise.fulfill(())
|
||||
}.catch { error in
|
||||
promise.reject(error)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func writeChannelValue(deviceId: Int, channelName: String, value : String, baseURL : String, authToken : String) -> Promise<Any> {
|
||||
let timestamp: Int = Int(Date().timeIntervalSince1970)
|
||||
var channelJson : JSON = JSON()
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// NavigationController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 5/29/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import ChameleonFramework
|
||||
|
||||
class NavigationController: UINavigationController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
self.navigationBar.tintColor = UIColor.flatSkyBlue()
|
||||
}
|
||||
|
||||
}
|
||||
37
pocloud/Controller/NavigationMenuController.swift
Normal file
37
pocloud/Controller/NavigationMenuController.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// NavigationMenuController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class NavigationMenuController: UITableViewController {
|
||||
|
||||
let appAuth = AppAuth()
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
}
|
||||
|
||||
@IBAction func logOutButtonPressed(_ sender: Any) {
|
||||
print("SHOULD LOG OUT")
|
||||
// appAuth.logOut()
|
||||
self.navigationController!.popToRootViewController(animated: true)
|
||||
// self.dismiss(animated: false) {
|
||||
// let mainVC = (UIApplication.shared.delegate!.window!?.rootViewController!)!
|
||||
// if let navController = mainVC.navigationController {
|
||||
// navController.popToRootViewController(animated: true)
|
||||
// } else {
|
||||
// print("NO NAV CONTROLLER")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5</string>
|
||||
<string>7</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSLocationUsageDescription</key>
|
||||
|
||||
@@ -44,6 +44,10 @@ class Address : Object {
|
||||
// return mapItem
|
||||
// }
|
||||
//
|
||||
public var streetAddress : String {
|
||||
return "\(street1)\n\(street2)\n\(city), \(state) \(zip)\n\(country)"
|
||||
}
|
||||
|
||||
override static func primaryKey() -> String? {
|
||||
return "id"
|
||||
}
|
||||
|
||||
24
pocloud/Model/Company.swift
Normal file
24
pocloud/Model/Company.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Company.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RealmSwift
|
||||
|
||||
class Company : Object {
|
||||
@objc dynamic var id : Int = 0
|
||||
@objc dynamic var name : String = ""
|
||||
@objc dynamic var tenantId : Int = 0
|
||||
@objc dynamic var addressId : Int = 0
|
||||
@objc dynamic var address : Address?
|
||||
|
||||
override static func primaryKey() -> String? {
|
||||
return "id"
|
||||
}
|
||||
|
||||
let gateways = List<Gateway>()
|
||||
}
|
||||
@@ -23,7 +23,9 @@ class Gateway : Object {
|
||||
@objc dynamic var userId : Int = 0
|
||||
@objc dynamic var address : Address?
|
||||
|
||||
|
||||
var devices = List<Device>()
|
||||
var parentCompany = LinkingObjects(fromType: Company.self, property: "gateways")
|
||||
|
||||
override static func primaryKey() -> String? {
|
||||
return "id"
|
||||
|
||||
44
pocloud/Model/Migrations.swift
Normal file
44
pocloud/Model/Migrations.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Migrations.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RealmSwift
|
||||
|
||||
class Migrations {
|
||||
|
||||
func checkSchema() {
|
||||
let config = Realm.Configuration(
|
||||
// Set the new schema version. This must be greater than the previously used
|
||||
// version (if you've never set a schema version before, the version is 0).
|
||||
schemaVersion: 1,
|
||||
|
||||
// Set the block which will be called automatically when opening a Realm with
|
||||
// a schema version lower than the one set above
|
||||
migrationBlock: { migration, oldSchemaVersion in
|
||||
// We haven’t migrated anything yet, so oldSchemaVersion == 0
|
||||
print(oldSchemaVersion)
|
||||
switch oldSchemaVersion {
|
||||
case 1:
|
||||
break
|
||||
default:
|
||||
// Nothing to do!
|
||||
self.zeroToOne(migration: migration)
|
||||
}
|
||||
})
|
||||
Realm.Configuration.defaultConfiguration = config
|
||||
print("Migration done")
|
||||
}
|
||||
|
||||
func zeroToOne(migration : Migration) {
|
||||
print("Performing migration from 0 to 1")
|
||||
migration.enumerateObjects(ofType: Company.className(), { (oldObject, newObject) in
|
||||
migration.delete(oldObject!)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,13 +22,13 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="POCloud" translatesAutoresizingMaskIntoConstraints="NO" id="1S2-PY-AeP">
|
||||
<rect key="frame" x="16" y="78" width="343" height="128"/>
|
||||
<rect key="frame" x="16" y="130" width="343" height="128"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="128" id="kdi-J3-yap"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nk0-L4-BTc">
|
||||
<rect key="frame" x="16" y="216" width="343" height="110"/>
|
||||
<rect key="frame" x="16" y="268" width="343" height="110"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="xGD-1W-wfk" userLabel="passwordField">
|
||||
<rect key="frame" x="0.0" y="40" width="343" height="30"/>
|
||||
@@ -89,7 +89,7 @@
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Login" id="Vcq-WU-7nG"/>
|
||||
<navigationItem key="navigationItem" title="Login" largeTitleDisplayMode="always" id="Vcq-WU-7nG"/>
|
||||
<connections>
|
||||
<outlet property="emailField" destination="ktz-LF-BMG" id="YD6-kd-Y0H"/>
|
||||
<outlet property="passwordField" destination="xGD-1W-wfk" id="grX-b5-xhC"/>
|
||||
@@ -98,7 +98,271 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="193" y="127"/>
|
||||
<point key="canvasLocation" x="-940" y="84"/>
|
||||
</scene>
|
||||
<!-- -->
|
||||
<scene sceneID="zqR-cL-CY1">
|
||||
<objects>
|
||||
<tableViewController id="IRa-Tu-z8L" customClass="NavigationMenuController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="rZD-k6-vfI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<sections>
|
||||
<tableViewSection id="BZs-uI-hiP">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="MOW-uN-hVD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MOW-uN-hVD" id="Zft-87-4vv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Map View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K2m-on-u83">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="WkR-Ec-bck"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="K2m-on-u83" secondAttribute="trailing" constant="16" id="itX-5w-OBv"/>
|
||||
<constraint firstItem="K2m-on-u83" firstAttribute="leading" secondItem="Zft-87-4vv" secondAttribute="leading" constant="16" id="ov7-hP-RzB"/>
|
||||
<constraint firstAttribute="bottom" secondItem="K2m-on-u83" secondAttribute="bottom" id="uWk-am-QXU"/>
|
||||
<constraint firstItem="K2m-on-u83" firstAttribute="top" secondItem="Zft-87-4vv" secondAttribute="top" id="v3E-fu-Z3h"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="yV3-Bs-nOb" kind="show" identifier="openMapView" id="vHY-2V-RrB"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="tgi-Lg-OUk">
|
||||
<rect key="frame" x="0.0" y="44" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="tgi-Lg-OUk" id="cHZ-P5-57P">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="List View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O2Q-ia-Znc">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="OUu-Sl-qO8"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="O2Q-ia-Znc" firstAttribute="top" secondItem="cHZ-P5-57P" secondAttribute="top" id="6b0-uT-Dyz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="O2Q-ia-Znc" secondAttribute="trailing" constant="16" id="X35-2D-Vmj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="O2Q-ia-Znc" secondAttribute="bottom" id="gii-t8-r0I"/>
|
||||
<constraint firstItem="O2Q-ia-Znc" firstAttribute="leading" secondItem="cHZ-P5-57P" secondAttribute="leading" constant="16" id="tNz-Jj-6c9"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="2zN-e5-x2c" kind="show" identifier="openListView" id="9Om-lw-Jgn"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="MFi-Ch-dpb">
|
||||
<rect key="frame" x="0.0" y="88" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MFi-Ch-dpb" id="uOu-qn-Bsk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Company View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PBz-lV-jm5">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="W4g-rH-3kB"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="PBz-lV-jm5" firstAttribute="top" secondItem="uOu-qn-Bsk" secondAttribute="top" id="eFS-1d-xye"/>
|
||||
<constraint firstItem="PBz-lV-jm5" firstAttribute="leading" secondItem="uOu-qn-Bsk" secondAttribute="leading" constant="16" id="uJV-EL-4pQ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="PBz-lV-jm5" secondAttribute="bottom" id="y0g-od-TRr"/>
|
||||
<constraint firstAttribute="trailing" secondItem="PBz-lV-jm5" secondAttribute="trailing" constant="16" id="y7M-Vh-JFu"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="gRf-OH-LM3" kind="show" identifier="openAdminView" id="gSm-yD-AQS"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="IRa-Tu-z8L" id="x7M-5j-lGC"/>
|
||||
<outlet property="delegate" destination="IRa-Tu-z8L" id="hPj-B4-IPb"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title=" " id="jEZ-M0-fct">
|
||||
<barButtonItem key="rightBarButtonItem" enabled="NO" title="Log Out" id="Efy-Wb-N0o">
|
||||
<connections>
|
||||
<action selector="logOutButtonPressed:" destination="IRa-Tu-z8L" id="fC3-XJ-dWk"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="BGw-nQ-anY" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1522" y="-1304"/>
|
||||
</scene>
|
||||
<!--Admin View-->
|
||||
<scene sceneID="luK-QG-5Bk">
|
||||
<objects>
|
||||
<tableViewController title="Admin View" id="gRf-OH-LM3" customClass="AdminViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="pRZ-8h-aCt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="companyCell" id="DRr-fl-mHP" customClass="AdminCompanyCell" customModule="pocloud" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="DRr-fl-mHP" id="P5X-PW-Uxh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="EhU-GL-Npw">
|
||||
<rect key="frame" x="16" y="0.0" width="325" height="43.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Company Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X2f-5T-wWU">
|
||||
<rect key="frame" x="0.0" y="11.5" width="278.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="cnt" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="16b-fu-GPA" customClass="PillUILabel" customModule="pocloud" customModuleProvider="target">
|
||||
<rect key="frame" x="278.5" y="8.5" width="46.5" height="26.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.32852089410000002" blue="0.57488495110000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="horizontalPad">
|
||||
<real key="value" value="3"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="verticalPad">
|
||||
<real key="value" value="3"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="16b-fu-GPA" firstAttribute="width" secondItem="X2f-5T-wWU" secondAttribute="width" multiplier="1:6" id="Thj-dG-e0H"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="EhU-GL-Npw" secondAttribute="trailing" id="SSP-KX-dUn"/>
|
||||
<constraint firstAttribute="bottom" secondItem="EhU-GL-Npw" secondAttribute="bottom" id="gWW-wI-VKJ"/>
|
||||
<constraint firstItem="EhU-GL-Npw" firstAttribute="top" secondItem="P5X-PW-Uxh" secondAttribute="top" id="rlm-TY-nIF"/>
|
||||
<constraint firstItem="EhU-GL-Npw" firstAttribute="leading" secondItem="P5X-PW-Uxh" secondAttribute="leading" constant="16" id="shl-Ek-QFo"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="companyCountLabel" destination="16b-fu-GPA" id="ycu-fG-ojM"/>
|
||||
<outlet property="companyNameLabel" destination="X2f-5T-wWU" id="wnq-TY-OZG"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="gRf-OH-LM3" id="0ea-wk-hcW"/>
|
||||
<outlet property="delegate" destination="gRf-OH-LM3" id="stD-ti-ZKX"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="Company View" id="mC8-zn-oFH">
|
||||
<barButtonItem key="rightBarButtonItem" title="Menu" id="3os-hB-xsh">
|
||||
<connections>
|
||||
<segue destination="Xem-jg-Xlm" kind="presentation" identifier="openMenu" id="LUR-lb-5qK"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<segue destination="1Oj-LF-SeF" kind="show" identifier="openCompanyDetailView" id="fe4-55-2K0"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="DB1-BB-Mof" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2492" y="-1305"/>
|
||||
</scene>
|
||||
<!--Title-->
|
||||
<scene sceneID="zaO-o6-5qR">
|
||||
<objects>
|
||||
<viewController id="1Oj-LF-SeF" customClass="CompanyViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="GRC-ek-5fe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="TeN-MF-HxZ">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<subviews>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="UFa-F1-ny6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="215.5"/>
|
||||
</mapView>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="tuB-TB-6oT">
|
||||
<rect key="frame" x="0.0" y="215.5" width="375" height="431.5"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="companyGatewayCell" id="vCb-SM-3BC">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="vCb-SM-3BC" id="jo4-sq-noy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="tuB-TB-6oT" firstAttribute="height" secondItem="UFa-F1-ny6" secondAttribute="height" multiplier="2:1" id="8yd-Ai-MxK"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="TeN-MF-HxZ" firstAttribute="trailing" secondItem="VXe-is-TrW" secondAttribute="trailing" id="Yqg-gC-eg1"/>
|
||||
<constraint firstItem="TeN-MF-HxZ" firstAttribute="leading" secondItem="VXe-is-TrW" secondAttribute="leading" id="cxy-jx-iWN"/>
|
||||
<constraint firstItem="VXe-is-TrW" firstAttribute="bottom" secondItem="TeN-MF-HxZ" secondAttribute="bottom" id="jjA-XJ-LOb"/>
|
||||
<constraint firstItem="TeN-MF-HxZ" firstAttribute="top" secondItem="VXe-is-TrW" secondAttribute="top" id="u4f-bI-9xa"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="VXe-is-TrW"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Title" id="Ja7-Gn-Q1G"/>
|
||||
<connections>
|
||||
<outlet property="mapView" destination="UFa-F1-ny6" id="q6c-IG-QE3"/>
|
||||
<outlet property="tableView" destination="tuB-TB-6oT" id="Vtm-TF-70f"/>
|
||||
<segue destination="T4w-Nz-H9R" kind="show" identifier="openGatewayDetail" id="DQm-0d-brY"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="7wS-xR-ms3" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3449" y="-1306"/>
|
||||
</scene>
|
||||
<!--Side Menu Navigation Controller-->
|
||||
<scene sceneID="gOX-yi-sFP">
|
||||
<objects>
|
||||
<navigationController id="Xem-jg-Xlm" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="kQ0-0P-nCC">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="IRa-Tu-z8L" kind="relationship" relationship="rootViewController" id="rm7-9q-AsM"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="2za-Iu-Z6p" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="580" y="-1305"/>
|
||||
</scene>
|
||||
<!--Map View-->
|
||||
<scene sceneID="pGu-9T-qKp">
|
||||
@@ -123,9 +387,9 @@
|
||||
</view>
|
||||
<toolbarItems/>
|
||||
<navigationItem key="navigationItem" title="Map" id="Qgs-vF-MTh">
|
||||
<barButtonItem key="rightBarButtonItem" title="List View" id="5K7-Fn-pYV">
|
||||
<barButtonItem key="rightBarButtonItem" title="Menu" id="5K7-Fn-pYV">
|
||||
<connections>
|
||||
<segue destination="2zN-e5-x2c" kind="show" identifier="openListView" id="23K-gs-PXS"/>
|
||||
<segue destination="Xem-jg-Xlm" kind="show" identifier="openMenu" id="Whl-9k-Yj2"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
@@ -137,24 +401,24 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ZSI-bq-lES" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1137" y="-305"/>
|
||||
<point key="canvasLocation" x="978" y="-227"/>
|
||||
</scene>
|
||||
<!--Detail View-->
|
||||
<!--Location Detail View-->
|
||||
<scene sceneID="LQ9-aX-3sA">
|
||||
<objects>
|
||||
<viewController title="Detail View" id="T4w-Nz-H9R" customClass="MapDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<viewController title="Location Detail View" id="T4w-Nz-H9R" customClass="MapDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="ecT-Qg-rFR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="xug-gE-FQz">
|
||||
<rect key="frame" x="0.0" y="109" width="375" height="200"/>
|
||||
<rect key="frame" x="0.0" y="65" width="375" height="200"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="200" id="tu9-2Y-yHN"/>
|
||||
</constraints>
|
||||
</mapView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="GatewayName" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="izu-lT-xWY">
|
||||
<rect key="frame" x="8" y="64" width="359" height="45"/>
|
||||
<rect key="frame" x="8" y="20" width="359" height="45"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="45" id="jbO-lj-xVg"/>
|
||||
</constraints>
|
||||
@@ -163,7 +427,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="tRH-fh-elp">
|
||||
<rect key="frame" x="0.0" y="319" width="375" height="304"/>
|
||||
<rect key="frame" x="0.0" y="275" width="375" height="392"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="dataViewCell" rowHeight="60" id="5Sz-TR-mVj" customClass="MapDetailDeviceCell" customModule="pocloud" customModuleProvider="target">
|
||||
@@ -237,9 +501,9 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Rio-1u-3O1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1984.8" y="126.38680659670166"/>
|
||||
<point key="canvasLocation" x="2001" y="-325"/>
|
||||
</scene>
|
||||
<!--Title-->
|
||||
<!--Device Detail-->
|
||||
<scene sceneID="q7c-Eh-Thg">
|
||||
<objects>
|
||||
<tableViewController id="eOb-fR-aFg" customClass="DeviceDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
@@ -301,7 +565,7 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<toolbarItems/>
|
||||
<navigationItem key="navigationItem" title="Title" id="sUT-g4-ZVO"/>
|
||||
<navigationItem key="navigationItem" title="Device Detail" id="sUT-g4-ZVO"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<refreshControl key="refreshControl" opaque="NO" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="4fv-Lb-C8k">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
|
||||
@@ -313,7 +577,7 @@
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="AE9-Tt-eth" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2780" y="456.52173913043481"/>
|
||||
<point key="canvasLocation" x="2001" y="532"/>
|
||||
</scene>
|
||||
<!--Channel Detail View Controller-->
|
||||
<scene sceneID="fDD-ow-Xi3">
|
||||
@@ -548,7 +812,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="qLG-JD-OG3" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3600.8000000000002" y="456.52173913043481"/>
|
||||
<point key="canvasLocation" x="3004" y="531"/>
|
||||
</scene>
|
||||
<!--History Graph View Controller-->
|
||||
<scene sceneID="WkV-VI-zTb">
|
||||
@@ -606,7 +870,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Add-tM-hJL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4352.8000000000002" y="456.52173913043481"/>
|
||||
<point key="canvasLocation" x="3972" y="530"/>
|
||||
</scene>
|
||||
<!--POCloud Data-->
|
||||
<scene sceneID="CNC-dV-jZs">
|
||||
@@ -616,9 +880,14 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<searchBar key="tableHeaderView" contentMode="redraw" id="z2g-Ak-4Pp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</searchBar>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="deviceListCell" id="rJT-U8-JVI">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="72" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rJT-U8-JVI" id="f7t-a1-NDN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
@@ -632,9 +901,9 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="POCloud Data" id="u6I-Ca-wA2">
|
||||
<barButtonItem key="rightBarButtonItem" title="Map View" id="yA7-No-AKb">
|
||||
<barButtonItem key="rightBarButtonItem" title="Menu" id="yA7-No-AKb">
|
||||
<connections>
|
||||
<segue destination="yV3-Bs-nOb" kind="show" identifier="openMapView" id="HF3-JU-BOm"/>
|
||||
<segue destination="Xem-jg-Xlm" kind="show" identifier="openMenu" id="qTd-vu-ryN"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
@@ -643,19 +912,20 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</refreshControl>
|
||||
<connections>
|
||||
<outlet property="searchBar" destination="z2g-Ak-4Pp" id="XeB-mp-w39"/>
|
||||
<segue destination="eOb-fR-aFg" kind="show" identifier="openDeviceDetailView" id="wUb-ND-zk7"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="uhB-7k-gae" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1136.8" y="456.52173913043481"/>
|
||||
<point key="canvasLocation" x="-212" y="84"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<!--Main Nav Controller-->
|
||||
<scene sceneID="zCd-ds-i4W">
|
||||
<objects>
|
||||
<navigationController id="iJg-Zc-arO" customClass="NavigationController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eWM-wh-jgG">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<navigationController id="iJg-Zc-arO" customClass="MainNavController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="eWM-wh-jgG">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="barTintColor" red="0.90823972225189209" green="0.92638683319091797" blue="0.9317171573638916" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</navigationBar>
|
||||
@@ -665,14 +935,16 @@
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="8gs-d8-KhR" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-774" y="128"/>
|
||||
<point key="canvasLocation" x="-1713" y="85"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="POCloud" width="2100" height="512"/>
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="CI7-x2-asH"/>
|
||||
<segue reference="9Om-lw-Jgn"/>
|
||||
<segue reference="wUb-ND-zk7"/>
|
||||
<segue reference="DQm-0d-brY"/>
|
||||
<segue reference="LUR-lb-5qK"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
</document>
|
||||
|
||||
45
pocloud/View/PillUILabel.swift
Normal file
45
pocloud/View/PillUILabel.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// PillUILabel.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/6/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@IBDesignable class PillUILabel : UILabel {
|
||||
@IBInspectable var verticalPad: CGFloat = 0
|
||||
@IBInspectable var horizontalPad: CGFloat = 0
|
||||
|
||||
func setup() {
|
||||
layer.cornerRadius = frame.height / 2
|
||||
clipsToBounds = true
|
||||
textAlignment = .center
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
setup()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
setup()
|
||||
}
|
||||
|
||||
override func prepareForInterfaceBuilder() {
|
||||
super.prepareForInterfaceBuilder()
|
||||
setup()
|
||||
}
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
let superSize = super.intrinsicContentSize
|
||||
let newWidth = superSize.width + superSize.height + (2 * horizontalPad)
|
||||
let newHeight = superSize.height + (2 * verticalPad)
|
||||
let newSize = CGSize(width: newWidth, height: newHeight)
|
||||
return newSize
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user