forked from Zero-zhou/iOS-Extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUIViewController+Ex.swift
156 lines (118 loc) · 5.25 KB
/
UIViewController+Ex.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//
// UIViewController+Ex.swift
//
// Created by Augus on 9/30/15.
// Copyright © 2015 iAugus. All rights reserved.
//
import UIKit
// MARK: -
extension UIViewController {
var isModal: Bool {
if presentingViewController != nil {
return true
} else if navigationController?.presentingViewController?.presentedViewController == navigationController {
return true
} else if tabBarController?.presentingViewController is UITabBarController {
return true
}
return false
}
}
// MARK: - Top bar (status bar + navigation bar)
extension UIViewController {
var statusBarFrame: CGRect {
return view.window?.convert(UIApplication.shared.statusBarFrame, to: view) ?? CGRect.zero
}
var topBarHeight: CGFloat {
var navBarHeight: CGFloat {
guard let bar = navigationController?.navigationBar else { return 0 }
return view.window?.convert(bar.frame, to: view).height ?? 0
}
let statusBarHeight = view.window?.convert(UIApplication.shared.statusBarFrame, to: view).height ?? 0
return statusBarHeight + navBarHeight
}
/**
While trying to present a new controller, current controller' bar may disappear temporary.
But I still need the real height of top bar.
- Why not set a constant (64.0 or 32.0)? Apple may change the constant in some device in the future.
*/
func topBarHeightWhenTemporaryDisappear() -> CGFloat {
let key = "kASTopBarHeightWhenTemporaryDisappear"
if UserDefaults.standard.value(forKey: key) == nil {
UserDefaults.standard.setValue(topBarHeight, forKey: key)
}
else if topBarHeight != 0 && topBarHeight != UserDefaults.standard.value(forKey: key) as! CGFloat {
UserDefaults.standard.setValue(topBarHeight, forKey: key)
}
return UserDefaults.standard.value(forKey: key) as! CGFloat
}
}
// MARK: - Keyboard notification
extension UIViewController {
func keyboardWillChangeFrameNotification(_ notification: Notification, scrollBottomConstant: NSLayoutConstraint) {
let duration = (notification as NSNotification).userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = (notification as NSNotification).userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
let keyboardBeginFrame = ((notification as NSNotification).userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let keyboardEndFrame = ((notification as NSNotification).userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let screenHeight = UIScreen.main.bounds.height
let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight
let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0)
UIView.animate(withDuration: duration.doubleValue,
delay: 0,
options: UIViewAnimationOptions(rawValue: UInt(curve.intValue << 16)),
animations: { () in
scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset
self.view.layoutIfNeeded()
},
completion: nil
)
}
}
// MARK: - Dismiss view controller
extension UIViewController {
@IBAction func dismissAnimated() {
dismiss(animated: true, completion: nil)
}
@IBAction func dismissWithoutAnimation() {
dismiss(animated: false, completion: nil)
}
@IBAction func popViewControllerAnimated() {
_ = navigationController?.popViewController(animated: true)
}
@IBAction func popViewControllerWithoutAnimation() {
_ = navigationController?.popViewController(animated: false)
}
}
// MARK: -
extension Selector {
static let dismissAnimated = #selector(UIViewController.dismissAnimated)
static let dismissWithoutAnimation = #selector(UIViewController.dismissWithoutAnimation)
static let popViewControllerAnimated = #selector(UIViewController.popViewControllerAnimated)
static let popViewControllerWithoutAnimation = #selector(UIViewController.popViewControllerWithoutAnimation)
}
// MAEK: - Edge dismiss gesture
extension UIViewController {
func configureScreenEdgeDismissGesture(_ edges: UIRectEdge = .left, animated: Bool = true, alsoForPad: Bool = false) {
if UIDevice.current.userInterfaceIdiom == .pad && !alsoForPad { return }
view.isUserInteractionEnabled = true
let selector = animated ? #selector(dismissAnimated) : #selector(dismissWithoutAnimation)
func left() {
let gesture = UIScreenEdgePanGestureRecognizer(target: self, action: selector)
gesture.edges = .left
view.addGestureRecognizer(gesture)
}
func right() {
let gesture = UIScreenEdgePanGestureRecognizer(target: self, action: selector)
gesture.edges = .right
view.addGestureRecognizer(gesture)
}
if edges == .left {
left()
} else if edges == .right {
right()
} else if edges == [.left, .right] {
left()
right()
}
}
}