4

I would like to be able to somehow detect if my app is running on a beta version of macOS 11, as there are some known bugs I want to inform users about. I only want to show such an alert to macOS 11 beta users, meaning not macOS 10.15 users nor users on the final version of macOS 11. I could of course just submit an app update to remove the alert when macOS 11 is close to being done, but it would be nice to have something reusable I could use in multiple apps and for future macOS beta versions.

Constraints:

  • The app is sandboxed.
  • The app is in the App Store, so no private APIs.
  • The app doesn't have a network entitlement, so the detection needs to be offline.
  • I don't want to bundle a list of known macOS build numbers and compare that.

My thinking is that maybe it's possible to use some kind of sniffing. Maybe there are some APIs that return different results when the macOS version is a beta version.

Sindre Sorhus
  • 62,972
  • 39
  • 168
  • 232
  • 1
    If it's running macOS 11 isn't it, by definition, running the beta? Once the OS goes final, update your app. There's no "beta" flag that I know of, and there's no way to know what the final (release) version number will be without a crystal ball. – James Bucanek Jul 05 '20 at 18:57
  • 3
    @JamesBucanek Your comment is already covered by the question text. Please read it. – Sindre Sorhus Jul 07 '20 at 18:21
  • Why checking random OS feature is better than hardcoding the version number? Checking the OS version is the common approach to such problems. Also, everyone is get used to nothing is working on macOS betas so maybe that's not a big of an issue. – Maxim Kosov Jul 08 '20 at 07:41
  • Maybe there's some difference you can find with Feedback Assistant? e.g. [When enrolling a macOS system in beta builds with the Beta Access Utility, the app is added to the Dock and aliased in /Utilities](https://developer.apple.com/bug-reporting/) – TheNextman Jul 08 '20 at 17:21
  • It's good question which I have too. I can think of loads of janky ways to do it but none offline, sandboxed and without hardcoding anything. The best I can come up with is to encode a "tested with version" into each release of the app. Then compare the host OS version and if the version is higher (excluding the last digit), display an "untested OS" warning. But Apple changing the numbering scheme to 11.0 makes it hard to predict the meaning of the numbers now. Will the next one be 12.0? What will 11.1 mean? Could also test for if it's between June and October :) – Nick Moore Oct 24 '20 at 08:17
  • This allegedly works for iOS not sure if it works for macOS, but macOS does have receipts so might work: https://stackoverflow.com/a/38984554/5389500 – Sentry.co Mar 30 '23 at 01:24

2 Answers2

3

I believe you're out of luck. About This Mac uses PrivateFrameworks/Seeding.framework, here the important disassembly:

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

So it seems this is a build time compiler flag. The plists in the framework don't contain this flag unfortunately.

Sample private API usage: kaloprominat/currentBuildIsSeed.py

For the crazy ones: It would be possible to read the binary and compare the assembly for the function. I'd start with the class-dump code, which gets you different fat binaries and the function offset.

catlan
  • 25,100
  • 8
  • 67
  • 78
0

This is far from perfect but macOS BigSur release notes mention:

Known Issues
In Swift, the authorizationStatus() property of CLLocationManager is incorrectly exposed as a method instead of a property. (62853845)

This^ is new API introduced in MacOS11 / iOS14

So one could detect this for this particular beta.

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
}
Kamil.S
  • 5,205
  • 2
  • 22
  • 51
  • That's clever, but it will most likely not work with future betas, so not very useful. I need something that works with all the betas, ideally with betas next year too. – Sindre Sorhus Jul 13 '20 at 19:11