如何获取iOS中的一些系统对象(Bundle、RootVC)持续更新

获取Bundle信息

获取Bundle中的信息,一个做法是读取info.plist文件,将读到的数据转成json来获取

swift 复制代码
var config: [String: Any]?
if let infoPlistPath = Bundle.main.url(forResource: "Info", withExtension: "plist") {
    do {
        let infoPlistData = try Data(contentsOf: infoPlistPath)
        if let dict = try PropertyListSerialization.propertyList(from: infoPlistData, options: [], format: nil) as? [String: Any] {
            config = dict
        }
    } catch {
        print(error)
    }
}

使用PropertyListSerialization.propertyList将infoPlistData转成dict,整个获取的过程比较原始,其实Apple有提供一些API直接获取

swift 复制代码
print(Bundle.main.object(forInfoDictionaryKey: "CFBundleName")!)
print(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")!)
print(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")!)

object是Bundle实例上的方法,forInfoDictionaryKey指定的key对应的value,整个使用体验比上一份读取info文件要好太多了。可以给Bundle添加extension,更方便调用

swift 复制代码
extension Bundle {
    var appName: String? {
        return object(forInfoDictionaryKey: "CFBundleName") as? String
    }
    var appVersion: String? {
        return object(forInfoDictionaryKey: "CFBundleVersion") as? String
    }
    var buildNumber: String? {
        return object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
    }
}

美滋滋啊......

而且object的API还比直接读取plist文件多一个功能,就是在有国际化的时候,object能直接获取到本地文件资源,可以自己试一下。

获取RootViewController

在iOS13之前,可以这样直接获取keyWindow和 root viewController UIApplication.shared.keyWindow?.rootViewController

但是iOS13支持了多视窗(multiple scenes),iOS15中UIApplication.shared.keyWindow?就要不支持了,所以iOS13之后,获取keyWindow的写法有些调整

swift 复制代码
extension UIApplication {
    var firstKeyWindow: UIWindow? {
        let windowScenes = UIApplication.shared.connectedScenes.compactMap{$0 as? UIWindowScene}
        let activeScene = windowScenes.filter { $0.activationState == .foregroundActive }
        let firstActiveScene = activeScene.first
        let keyWindow = firstActiveScene?.keyWindow
        return keyWindow
    }
}
  • UIApplication.shared.connectedScenes获取到所有视窗,并通过compactMap转成UIWindowScene对象
  • Multiple Windows意味着会获取到不止一个active scene,默认获取到所有activeScene的第一个
  • 从active scene对象上获取keyWindow对象返回

之后可以用这个extension的firstKeyWindow获取rootViewController(有点像iOS13之前的用法了) let vc = UIApplication.shared.firstKeyWindow?.rootViewController

UIWindowScene.keyWindow到iOS15才支持,iOS13中需要我们自己手动过滤下keyWindow的筛选,代码改动如下(更紧凑些):

swift 复制代码
var firstKeyWindow: UIWindow? {
    return UIApplication.shared.connectedScenes
        .compactMap { $0 as? UIWindowScene }
        .filter { $0.activationState == .foregroundActive }
        .first?.windows
        .first(where: \.isKeyWindow)
}

使用了 window.first(where: \.isKeyWindow)来获取keywindow,它是UIWindow的一个属性

相关推荐
初级代码游戏9 小时前
iOS只剩美工了吗?时间都被遮盖看不清了
ios·界面设计·美工
2501_9159184117 小时前
iOS 开发中证书创建与管理中的常见问题
android·ios·小程序·https·uni-app·iphone·webview
00后程序员张17 小时前
IOScer 开发环境证书包括哪些,证书、描述文件与 App ID 的协同管理实践
android·ios·小程序·https·uni-app·iphone·webview
江东小bug王17 小时前
深入理解 UITabBarController:代理方法与 ViewController 生命周期的执行顺序(含 UINavigationController 场景)
ios
阿里云云原生17 小时前
RUM 赋能 iOS App 稳定:从异常体系到监控方案的全方位解析!
ios·云原生
Zfox_18 小时前
无缝穿越系统边界:节点小宝4.0如何让我的Mac/iOS像访问本地盘一样操控Windows
windows·macos·ios·节点小宝
Zender Han20 小时前
Flutter 图片裁剪插件 image_cropper 最新版介绍与使用教程
android·flutter·ios
方白羽21 小时前
Android 与 iOS 动态更换应用图标实现方案
android·ios·app
Haha_bj21 小时前
Swift——高阶函数(map、filter、reduce、forEach、sorted、contains……)
ios·app·swift
妮妮分享1 天前
维智地图如何集成
开发语言·ios·swift