【问题标题】:Detect if app is running on a macOS beta version检测应用程序是否在 macOS 测试版上运行
【发布时间】:2020-10-25 20:55:33
【问题描述】:

我希望能够以某种方式检测我的应用是否在 macOS 11 的测试版上运行,因为我想告知用户一些已知的错误。我只想向 macOS 11 beta 用户显示这样的警报,这意味着既不是 macOS 10.15 用户也不是 macOS 11 最终版本的用户。我当然可以提交一个应用程序更新以在 macOS 11 接近完成时删除警报,但如果有一些可重复使用的东西我可以在多个应用程序和未来的 macOS beta 版本中使用,那就太好了。

约束:

  • 应用已被沙盒化。
  • 该应用在 App Store 中,因此没有私有 API。
  • 该应用没有网络授权,因此需要离线检测。
  • 我不想捆绑已知 macOS 内部版本号的列表并进行比较。

我的想法是,也许可以使用某种嗅探。 macOS 版本为 beta 版本时,可能有一些 API 会返回不同的结果。

【问题讨论】:

  • 如果它运行的是 macOS 11,根据定义,它不是运行 Beta 版吗?操作系统完成后,更新您的应用程序。据我所知,没有“beta”标志,没有水晶球也无法知道最终(发布)版本号是多少。
  • @JamesBucanek 您的评论已包含在问题文本中。请阅读。
  • 为什么检查随机操作系统功能比硬编码版本号更好?检查操作系统版本是解决此类问题的常用方法。此外,每个人都习惯于在 macOS 测试版上工作,所以这可能不是什么大问题。
  • 这是个好问题,我也有。我可以想到很多笨拙的方法来做到这一点,但没有离线、沙盒和没有硬编码任何东西。我能想到的最好的方法是将“测试版本”编码到应用程序的每个版本中。然后比较主机操作系统版本,如果版本更高(不包括最后一位),则显示“未经测试的操作系统”警告。但是 Apple 将编号方案更改为 11.0 使得现在很难预测这些数字的含义。下一个是12.0吗? 11.1 意味着什么?也可以测试它是否在 6 月和 10 月之间:)

标签: swift macos cocoa beta macos-big-sur


【解决方案1】:

我相信你运气不好。 About This Mac 使用 PrivateFrameworks/Seeding.framework,这里是重要的反汇编:

/* @class SDBuildInfo */
+(char)currentBuildIsSeed {
    return 0x0;
}

所以这似乎是一个构建时编译器标志。不幸的是,框架中的 plist 不包含此标志。

私有 API 使用示例:kaloprominat/currentBuildIsSeed.py

对于疯狂的:可以读取二进制文件并比较函数的程序集。我将从类转储代码开始,它会为您提供不同的胖二进制文件和函数偏移量。

【讨论】:

  • 这个想法不错,但不适用于沙盒应用程序,我提到这是一个约束。
  • @catlan,在进一步研究这种方法后,我已经能够直接访问捆绑包并检索这个值。
【解决方案2】:

这远非完美,但 macOS BigSur release notes 提及:

已知问题
在 Swift 中,CLLocationManager 的 authorizationStatus() 属性被错误地公开为方法而不是属性。 (62853845)

这个^是MacOS11/iOS14引入的newAPI

所以人们可以为这个特定的测试版检测到这一点。

import CoreLocation
func isMacOS11Beta() -> Bool {
    var propertiesCount = UInt32()
    let classToInspect = CLLocationManager.self
    var isMacOS11OrHigher = false
    var isMacOS11Beta = false
    let propertiesInAClass = class_copyPropertyList(CLLocationManager.self, &propertiesCount)
    if classToInspect.responds(to: NSSelectorFromString("authorizationStatus")) {
        isMacOS11OrHigher = true
        isMacOS11Beta = true
        for i in 0 ..< Int(propertiesCount) {
            if let property = propertiesInAClass?[i], let propertyName = NSString(utf8String: property_getName(property)) as String? {
                if propertyName == "authorizationStatus" {
                    isMacOS11Beta = false
                }
            }
        }
        free(propertiesInAClass)
    }
    return isMacOS11OrHigher && isMacOS11Beta
}

【讨论】:

  • 这很聪明,但它很可能不适用于未来的测试版,因此不是很有用。我需要适用于所有测试版的东西,理想情况下也适用于明年的测试版。
猜你喜欢
  • 2019-11-22
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2017-03-08
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
相关资源
最近更新 更多