2025-10-27 21:55:05 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KeyBoardPrefixHeader.pch
|
|
|
|
|
|
// keyBoard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Mac on 2025/10/27.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef KeyBoardPrefixHeader_pch
|
|
|
|
|
|
#define KeyBoardPrefixHeader_pch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Bugly
|
|
|
|
|
|
#define BuglyId @"5736ce7a19"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 三方
|
|
|
|
|
|
#import <Masonry/Masonry.h>
|
2025-10-31 13:05:34 +08:00
|
|
|
|
// 公共配置
|
|
|
|
|
|
#import "KBConfig.h"
|
2025-10-27 21:55:05 +08:00
|
|
|
|
|
2025-10-29 16:26:57 +08:00
|
|
|
|
/// 系统
|
|
|
|
|
|
#import <UIKit/UIKit.h>
|
2025-10-29 19:13:35 +08:00
|
|
|
|
#import "KBHUD.h"
|
2025-10-29 20:57:45 +08:00
|
|
|
|
#import "KBNetworkManager.h"
|
|
|
|
|
|
|
2025-10-29 16:26:57 +08:00
|
|
|
|
|
2025-10-29 14:17:26 +08:00
|
|
|
|
/// 项目
|
2025-11-06 21:38:58 +08:00
|
|
|
|
#import "UIView+KBShadow.h"
|
|
|
|
|
|
#import "UIImage+KBColor.h"
|
|
|
|
|
|
#import "UIColor+Extension.h"
|
|
|
|
|
|
|
2025-11-03 15:04:19 +08:00
|
|
|
|
#import "UIViewController+Extension.h"
|
2025-10-29 14:17:26 +08:00
|
|
|
|
#import "BaseNavigationController.h"
|
2025-10-29 15:02:37 +08:00
|
|
|
|
#import "BaseTableView.h"
|
|
|
|
|
|
#import "BaseCell.h"
|
2025-11-03 16:37:28 +08:00
|
|
|
|
#import "KBLocalizationManager.h" // 全局多语言封装
|
2025-10-29 14:17:26 +08:00
|
|
|
|
|
2025-10-27 21:55:05 +08:00
|
|
|
|
|
2025-10-29 16:26:57 +08:00
|
|
|
|
//-----------------------------------------------宏定义全局----------------------------------------------------------/
|
2025-10-30 20:53:44 +08:00
|
|
|
|
// 通用链接(Universal Links)统一配置
|
|
|
|
|
|
// 仅需修改这里的域名/前缀,工程内所有使用 UL 的地方都会同步。
|
2025-11-05 18:10:56 +08:00
|
|
|
|
#define KB_UL_BASE @"https://app.tknb.net/ul" // 与 Associated Domains 一致
|
2025-10-30 20:53:44 +08:00
|
|
|
|
#define KB_UL_LOGIN KB_UL_BASE @"/login"
|
|
|
|
|
|
#define KB_UL_SETTINGS KB_UL_BASE @"/settings"
|
|
|
|
|
|
|
2025-10-29 16:26:57 +08:00
|
|
|
|
/// UI 尺寸/设备宏
|
|
|
|
|
|
// 屏幕尺寸
|
|
|
|
|
|
#define KB_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
|
|
|
|
|
|
#define KB_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
|
|
|
|
|
|
#define KB_ONE_PIXEL (1.0 / [UIScreen mainScreen].scale)
|
|
|
|
|
|
|
|
|
|
|
|
// 基础高度
|
|
|
|
|
|
#define KB_NAVBAR_BASE_HEIGHT 44.0
|
|
|
|
|
|
#define KB_TABBAR_BASE_HEIGHT 49.0
|
|
|
|
|
|
|
2025-11-06 19:19:12 +08:00
|
|
|
|
#define COLOR_WITH_RGB(R,G,B,A) [UIColor colorWithRed:R green:G blue:B alpha:A]
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-10-29 16:26:57 +08:00
|
|
|
|
// 当前 KeyWindow(iOS 13 场景化兼容)
|
|
|
|
|
|
static inline UIWindow *KB_KeyWindow(void) {
|
|
|
|
|
|
UIWindow *window = nil;
|
|
|
|
|
|
if (@available(iOS 13.0, *)) {
|
|
|
|
|
|
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
|
|
|
|
|
|
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
|
|
|
|
|
|
UIWindowScene *ws = (UIWindowScene *)scene;
|
|
|
|
|
|
for (UIWindow *w in ws.windows) {
|
|
|
|
|
|
if (w.isKeyWindow) { window = w; break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
if (window) { break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!window) { window = UIApplication.sharedApplication.windows.firstObject; }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
window = UIApplication.sharedApplication.keyWindow;
|
|
|
|
|
|
}
|
|
|
|
|
|
return window;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Safe Area
|
|
|
|
|
|
static inline UIEdgeInsets KB_SafeAreaInsets(void) {
|
|
|
|
|
|
if (@available(iOS 11.0, *)) {
|
|
|
|
|
|
UIWindow *w = KB_KeyWindow();
|
|
|
|
|
|
return w ? w.safeAreaInsets : UIEdgeInsetsZero;
|
|
|
|
|
|
}
|
|
|
|
|
|
return UIEdgeInsetsZero;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline CGFloat KB_SafeAreaTop(void) { return KB_SafeAreaInsets().top; }
|
|
|
|
|
|
static inline CGFloat KB_SafeAreaBottom(void) { return KB_SafeAreaInsets().bottom; }
|
|
|
|
|
|
|
|
|
|
|
|
// 状态栏高度(iOS13+ 兼容)
|
|
|
|
|
|
static inline CGFloat KB_StatusBarHeight(void) {
|
|
|
|
|
|
if (@available(iOS 13.0, *)) {
|
|
|
|
|
|
UIWindow *w = KB_KeyWindow();
|
|
|
|
|
|
UIStatusBarManager *m = w.windowScene.statusBarManager;
|
|
|
|
|
|
return m ? m.statusBarFrame.size.height : 0.0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return UIApplication.sharedApplication.statusBarFrame.size.height;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 导航栏+状态栏总高度、TabBar 高度、是否异形屏
|
|
|
|
|
|
#define KB_STATUSBAR_HEIGHT (KB_StatusBarHeight())
|
|
|
|
|
|
#define KB_NAV_TOTAL_HEIGHT (KB_NAVBAR_BASE_HEIGHT + KB_StatusBarHeight())
|
|
|
|
|
|
#define KB_TABBAR_HEIGHT (KB_TABBAR_BASE_HEIGHT + KB_SafeAreaBottom())
|
|
|
|
|
|
#define KB_IS_IPHONEX_SERIES (KB_SafeAreaBottom() > 0.0)
|
|
|
|
|
|
|
2025-10-27 21:55:05 +08:00
|
|
|
|
|
2025-11-06 15:16:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --- 设备特性:是否为带刘海机型(iPhone X 及以后异形屏)---
|
|
|
|
|
|
// 说明:在 iPhone 12 等机型底部会有 34px 安全区,这里通过安全区来判断是否为“刘海屏”。
|
|
|
|
|
|
// 注意:使用到 UIKit,这里自行引入,避免依赖 PCH 的包含顺序。
|
|
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
|
|
static inline BOOL KBDeviceHasNotchRuntime(void) {
|
|
|
|
|
|
if (@available(iOS 11.0, *)) {
|
|
|
|
|
|
UIWindow *window = nil;
|
|
|
|
|
|
if (@available(iOS 13.0, *)) {
|
|
|
|
|
|
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
|
|
|
|
|
|
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
|
|
|
|
|
|
UIWindowScene *ws = (UIWindowScene *)scene;
|
|
|
|
|
|
for (UIWindow *w in ws.windows) { if (w.isKeyWindow) { window = w; break; } }
|
|
|
|
|
|
if (window) { break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!window) { window = UIApplication.sharedApplication.windows.firstObject; }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
window = UIApplication.sharedApplication.keyWindow;
|
|
|
|
|
|
}
|
|
|
|
|
|
return window.safeAreaInsets.bottom > 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return NO;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef KB_DEVICE_HAS_NOTCH
|
|
|
|
|
|
#define KB_DEVICE_HAS_NOTCH (KBDeviceHasNotchRuntime())
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2025-11-06 16:57:28 +08:00
|
|
|
|
// --- 获取当前可用的 UINavigationController ---
|
|
|
|
|
|
// 说明:
|
|
|
|
|
|
// 1. 优先取最顶层可见 VC(见 UIViewController+Extension),再解析其所在的导航容器;
|
|
|
|
|
|
// 2. 兼容被 UITabBarController 包裹、直接为 UINavigationController、或普通 VC 嵌套等场景;
|
|
|
|
|
|
// 3. 若无法获取,返回 nil。
|
|
|
|
|
|
static inline __kindof UINavigationController *KB_CurrentNavigationController(void) {
|
|
|
|
|
|
UIViewController *top = [UIViewController kb_topMostViewController];
|
|
|
|
|
|
if (!top) {
|
|
|
|
|
|
UIWindow *w = KB_KeyWindow();
|
|
|
|
|
|
top = w.rootViewController;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!top) return nil;
|
|
|
|
|
|
|
|
|
|
|
|
// 直接就是导航控制器
|
|
|
|
|
|
if ([top isKindOfClass:[UINavigationController class]]) {
|
|
|
|
|
|
return (UINavigationController *)top;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 顶层是 TabBar,取选中的子控制器
|
|
|
|
|
|
if ([top isKindOfClass:[UITabBarController class]]) {
|
|
|
|
|
|
UITabBarController *tab = (UITabBarController *)top;
|
|
|
|
|
|
UIViewController *sel = tab.selectedViewController ?: tab.viewControllers.firstObject;
|
|
|
|
|
|
if ([sel isKindOfClass:[UINavigationController class]]) return (UINavigationController *)sel;
|
|
|
|
|
|
return sel.navigationController ?: nil;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 普通 VC,取其所属导航
|
|
|
|
|
|
if (top.navigationController) return top.navigationController;
|
|
|
|
|
|
|
|
|
|
|
|
// 兜底:尝试从 root 解析
|
|
|
|
|
|
UIViewController *root = KB_KeyWindow().rootViewController;
|
|
|
|
|
|
if ([root isKindOfClass:[UINavigationController class]]) return (UINavigationController *)root;
|
|
|
|
|
|
if ([root isKindOfClass:[UITabBarController class]]) {
|
|
|
|
|
|
UIViewController *sel = ((UITabBarController *)root).selectedViewController;
|
|
|
|
|
|
if ([sel isKindOfClass:[UINavigationController class]]) return (UINavigationController *)sel;
|
|
|
|
|
|
return sel.navigationController ?: nil;
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 简便宏:直接当做属性来用,例如:`[KB_CURRENT_NAV pushViewController:vc animated:YES];`
|
|
|
|
|
|
#ifndef KB_CURRENT_NAV
|
|
|
|
|
|
#define KB_CURRENT_NAV (KB_CurrentNavigationController())
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2025-10-27 21:55:05 +08:00
|
|
|
|
#endif /* KeyBoardPrefixHeader_pch */
|