forked from SwiftKickMobile/SwiftMessages
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUIViewController+Extensions.swift
101 lines (93 loc) · 4.44 KB
/
UIViewController+Extensions.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
//
// UIViewController+Extensions.swift
// SwiftMessages
//
// Created by Timothy Moose on 8/5/16.
// Copyright © 2016 SwiftKick Mobile LLC. All rights reserved.
//
import UIKit
extension UIViewController {
func sm_selectPresentationContextTopDown(_ config: SwiftMessages.Config) -> UIViewController {
let topBottomStyle = config.presentationStyle.topBottomStyle
if let presented = presentedViewController {
return presented.sm_selectPresentationContextTopDown(config)
} else if case .top? = topBottomStyle, let navigationController = sm_selectNavigationControllerTopDown() {
return navigationController
} else if case .bottom? = topBottomStyle, let tabBarController = sm_selectTabBarControllerTopDown() {
return tabBarController
}
return WindowViewController.newInstance(config: config)
}
fileprivate func sm_selectNavigationControllerTopDown() -> UINavigationController? {
if let presented = presentedViewController {
return presented.sm_selectNavigationControllerTopDown()
} else if let navigationController = self as? UINavigationController {
if navigationController.sm_isVisible(view: navigationController.navigationBar) {
return navigationController
}
return navigationController.topViewController?.sm_selectNavigationControllerTopDown()
} else if let tabBarController = self as? UITabBarController {
return tabBarController.selectedViewController?.sm_selectNavigationControllerTopDown()
}
return nil
}
fileprivate func sm_selectTabBarControllerTopDown() -> UITabBarController? {
if let presented = presentedViewController {
return presented.sm_selectTabBarControllerTopDown()
} else if let navigationController = self as? UINavigationController {
return navigationController.topViewController?.sm_selectTabBarControllerTopDown()
} else if let tabBarController = self as? UITabBarController {
if tabBarController.sm_isVisible(view: tabBarController.tabBar) {
return tabBarController
}
return tabBarController.selectedViewController?.sm_selectTabBarControllerTopDown()
}
return nil
}
func sm_selectPresentationContextBottomUp(_ config: SwiftMessages.Config) -> UIViewController {
let topBottomStyle = config.presentationStyle.topBottomStyle
if let parent = parent {
if let navigationController = parent as? UINavigationController {
if case .top? = topBottomStyle, navigationController.sm_isVisible(view: navigationController.navigationBar) {
return navigationController
}
return navigationController.sm_selectPresentationContextBottomUp(config)
} else if let tabBarController = parent as? UITabBarController {
if case .bottom? = topBottomStyle, tabBarController.sm_isVisible(view: tabBarController.tabBar) {
return tabBarController
}
return tabBarController.sm_selectPresentationContextBottomUp(config)
}
}
if self.view is UITableView {
// Never select scroll view as presentation context
// because, you know, it scrolls.
if let parent = self.parent {
return parent.sm_selectPresentationContextBottomUp(config)
} else {
return WindowViewController.newInstance(config: config)
}
}
return self
}
func sm_isVisible(view: UIView) -> Bool {
if view.isHidden { return false }
if view.alpha == 0.0 { return false }
let frame = self.view.convert(view.bounds, from: view)
if !self.view.bounds.intersects(frame) { return false }
return true
}
}
extension SwiftMessages.PresentationStyle {
/// A temporary workaround to allow custom presentation contexts using `TopBottomAnimation`
/// to display properly behind bars. THe long term solution is to refactor all of the
/// presentation context logic to work with safe area insets.
var topBottomStyle: TopBottomAnimation.Style? {
switch self {
case .top: return .top
case .bottom: return .bottom
case .custom(let animator): return (animator as? TopBottomAnimation)?.style
case .center: return nil
}
}
}