252 lines
7.7 KiB
Swift
Executable File
252 lines
7.7 KiB
Swift
Executable File
//
|
||
// UIWindow+Ext.swift
|
||
// DouYinSwift5
|
||
//
|
||
// Created by lym on 2020/7/23.
|
||
// Copyright © 2020 lym. All rights reserved.
|
||
//
|
||
import UIKit
|
||
|
||
@objc extension UIWindow {
|
||
static var key: UIWindow? {
|
||
if #available(iOS 13, *) {
|
||
return UIApplication.shared.connectedScenes
|
||
.map { $0 as? UIWindowScene }
|
||
.compactMap { $0 }
|
||
.first?.windows
|
||
.filter { $0.isKeyWindow }.first
|
||
} else {
|
||
return UIApplication.shared.windows
|
||
.filter { $0.isKeyWindow }
|
||
.first
|
||
}
|
||
}
|
||
|
||
static var applicationKey: UIWindow? {
|
||
if #available(iOS 13, *) {
|
||
var window: UIWindow?
|
||
let connectedScenes = UIApplication.shared.connectedScenes
|
||
.map { $0 as? UIWindowScene }
|
||
.compactMap { $0 }
|
||
connectedScenes.forEach { scene in
|
||
window = scene.windows.filter { $0.tag == 1024 }.first
|
||
}
|
||
return window
|
||
} else {
|
||
return UIApplication.shared.windows.first(where: { $0.tag == 1024 })
|
||
}
|
||
}
|
||
|
||
/// 获取当前激活的 SceneDelegate
|
||
static var currentSceneDelegate: SceneDelegate? {
|
||
if let scene = UIApplication.shared.connectedScenes
|
||
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
|
||
return scene.delegate as? SceneDelegate
|
||
}
|
||
return nil
|
||
}
|
||
|
||
/// 获取当前激活窗口
|
||
static var current: UIWindow? {
|
||
if let scene = UIApplication.shared.connectedScenes
|
||
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
|
||
return scene.windows.first(where: { $0.isKeyWindow })
|
||
}
|
||
return nil
|
||
}
|
||
|
||
static var safeAreaInsets: UIEdgeInsets {
|
||
return UIWindow.key?.safeAreaInsets ?? UIEdgeInsets.zero
|
||
}
|
||
|
||
static var safeAreaBottom: CGFloat {
|
||
return safeAreaInsets.bottom
|
||
}
|
||
|
||
static var statusBarFrame: CGRect {
|
||
if #available(iOS 13.0, *) {
|
||
return key?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
|
||
} else {
|
||
return UIApplication.shared.statusBarFrame
|
||
}
|
||
}
|
||
|
||
static var statusBarHeight: CGFloat {
|
||
return statusBarFrame.size.height
|
||
}
|
||
|
||
static var navBarHeight: CGFloat {
|
||
return getTopViewController()?.navigationController?.navigationBar.frame.height ?? 44
|
||
}
|
||
|
||
static var navBarTotalHeight: CGFloat {
|
||
return statusBarHeight + navBarHeight
|
||
}
|
||
|
||
static var tabBarFrame: CGRect {
|
||
if let vc = key?.rootViewController as? UITabBarController {
|
||
if #available(iOS 11.0, *) {
|
||
return vc.tabBar.frame
|
||
} else {
|
||
return .zero
|
||
}
|
||
} else {
|
||
return .zero
|
||
}
|
||
}
|
||
|
||
static var tabBarHeight: CGFloat {
|
||
if #available(iOS 11.0, *) {
|
||
return tabBarTotalHeight - (key?.safeAreaInsets.bottom ?? 0)
|
||
} else {
|
||
return tabBarTotalHeight
|
||
}
|
||
}
|
||
|
||
static var tabBarTotalHeight: CGFloat {
|
||
return tabBarFrame.height
|
||
}
|
||
|
||
class func getTopViewController(base: UIViewController? = UIWindow.getTopDisplayWindow()?.rootViewController) -> UIViewController? {
|
||
if let nav = base as? UINavigationController {
|
||
return getTopViewController(base: nav.viewControllers.last)
|
||
|
||
} else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
|
||
return getTopViewController(base: selected)
|
||
|
||
} else if let presented = base?.presentedViewController {
|
||
return getTopViewController(base: presented)
|
||
}
|
||
return base
|
||
}
|
||
|
||
class func getTopNavigationController() -> CLNavigationController?{
|
||
return getTopViewController()?.navigationController as? CLNavigationController
|
||
}
|
||
|
||
class func getTopDisplayWindow() -> UIWindow? {
|
||
var theWindow = applicationKey
|
||
let windows = UIApplication.shared.windows
|
||
|
||
// windows.forEach { w in
|
||
// dlog("获取的windows getTopDisplayWindow = \(w.self), isKey = \(w.isKeyWindow)")
|
||
// }
|
||
|
||
for window in windows.reversed() {
|
||
// 需要过滤掉的类型
|
||
// ⚠️ Swift创建的Window为{ProjectName}.NoticeWindow,带命名空间,注意判断逻辑的写法:NSClassFromString("LegendTeam.NoticeWindow")or window.isKind(of: NoticeWindow.self)
|
||
// if window.isKind(of: NoticeWindow.self) {
|
||
// continue
|
||
// }
|
||
|
||
// UIRemoteKeyboardWindow
|
||
// UITextEffectsWindow
|
||
if let class1 = NSClassFromString("UIRemoteKeyboardWindow") {
|
||
if window.isKind(of: class1) {
|
||
//dlog("过滤掉的window UIRemoteKeyboardWindow")
|
||
continue
|
||
}
|
||
}
|
||
if let class2 = NSClassFromString("UITextEffectsWindow") {
|
||
if window.isKind(of: class2) {
|
||
//dlog("过滤掉的window UITextEffectsWindow")
|
||
continue
|
||
}
|
||
}
|
||
if let class3 = NSClassFromString("EGChatRoomFloatWindow") {
|
||
if window.isKind(of: class3) {
|
||
//dlog("过滤掉的window EGChatRoomFloatWindow")
|
||
continue
|
||
}
|
||
}
|
||
|
||
if let class4 = NSClassFromString("PhoneFloatWindow") {
|
||
if window.isKind(of: class4) {
|
||
//dlog("过滤掉的window PhoneFloatWindow")
|
||
continue
|
||
}
|
||
}
|
||
|
||
if let class5 = NSClassFromString("PhoneWindow") {
|
||
if window.isKind(of: class5) {
|
||
//dlog("过滤掉的window PhoneWindow")
|
||
continue
|
||
}
|
||
}
|
||
|
||
// if ChatRoomRoute.isMiniMize() {
|
||
// if let class4 = NSClassFromString("ChatRoomWindow") {
|
||
// if window.isKind(of: class4) {
|
||
// dlog("过滤掉的window ChatRoomWindow, 聊天室缩小状态")
|
||
// continue
|
||
// }
|
||
// }
|
||
// }
|
||
|
||
if !window.isHidden, window.alpha == 1 {
|
||
theWindow = window
|
||
// dlog("获取的window2 = \(window), type = \(window.self)")
|
||
break
|
||
}
|
||
}
|
||
return theWindow
|
||
}
|
||
}
|
||
|
||
extension UIScreen {
|
||
static var width: CGFloat {
|
||
return UIScreen.main.bounds.width
|
||
}
|
||
|
||
static var height: CGFloat {
|
||
return UIScreen.main.bounds.height
|
||
}
|
||
|
||
/// 屏幕尺寸(CGSize)
|
||
static var size: CGSize {
|
||
return UIScreen.main.bounds.size
|
||
}
|
||
|
||
/// 屏幕比例(宽 / 高)
|
||
static var aspectRatio: CGFloat {
|
||
return width / height
|
||
}
|
||
|
||
/// 是否是窄屏(如 iPhone SE)
|
||
static var isNarrow: Bool {
|
||
return width <= 320
|
||
}
|
||
}
|
||
|
||
extension UIDevice {
|
||
static var isIphoneX: Bool {
|
||
if UIDevice.current.userInterfaceIdiom != .phone {
|
||
return true
|
||
}
|
||
if #available(iOS 11.0, *) {
|
||
let bottom = UIWindow.safeAreaInsets.bottom
|
||
if bottom > 0.0 {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
/// 获取屏幕系数缩放后的值
|
||
static func DP(x: CGFloat) -> CGFloat {
|
||
let standardWidth: CGFloat = 375.0
|
||
let scale = UIScreen.width / standardWidth
|
||
return x * scale
|
||
}
|
||
|
||
/// 获取屏幕系数缩放后的值,最大不超过原值
|
||
static func DP(max: CGFloat) -> CGFloat {
|
||
let x = DP(x: max)
|
||
if x > max {
|
||
return max
|
||
} else {
|
||
return x
|
||
}
|
||
}
|
||
}
|