How to detect if an iOS app is running on an M1 mac?

Viewed 6411

I offer an iOS app on the App Store. With the launch of Apple's M1 Macs it's possible to run iOS apps on macOS. I want to prevent that my app is used on macOS, for example by throwing an exception after launch or calling exit(0) at a later time.

How can I detect that the app is running on an M1 Mac?

To a certain extent, iOS apps running on Macs seem to report themselves as iPads1, so this rules out some common ways to identify the device.

Some details to provide context:

  1. I already removed the app from the Mac App Store on App Store Connect.

  2. The app is made and optimized for touch screens. The current version would offer a very bad user experience when run on macOS. It would require many changes and a lot of effort to make it a good Mac app. I don't have any plans, let alone the resources to do that.

  3. On the surface this might seem similar to the question "How can I detect if my app runs on a jailbroken device?". Technically, this might be correct, and I understand that it's generally not advisable to implement jailbreak detection to prevent IAP hacks etc. An important difference is that Apple is actively trying to prevent jailbreaks and strongly discourages users from doing so, which seems to keeps the jailbreak community rather small and off mainstream, but on the other hand, Apple obviously wants to have as many iOS apps as possible available on Macs. It's currently very easy to run iOS apps on Macs, even if they are not offered in the Mac App Store. There are instructions on popular tech blogs like MacRumors and 9to5mac. I want to make sure that at least this easy way to run the app on a mac is prevented.

  4. Many implementation details in this app have been developed under the assumption that the app will only ever run in an iOS sandbox that users don't have easy access to. Now, it's probably much easier for users to run the app with modified resources, user defaults or contents of directories like Application Support, including files that I assumed to be always immutable. If users find a way to access content in the app that usually requires in-app purchases or subscriptions, for example by fudging .plists or renaming resource files in an unexpected way, it's a real business risk.


1 At the time of the original post, M1 Macs appeared to report themselves via hw.machine as model identifier iPad8,6. A tweet that provided a few more details has since been removed.

5 Answers

Apple's framework allows you to detect if the app is running as an iOS app on Mac by using the process info flag isiOSAppOnMac.

This flag is available from iOS 14.0 and therefore needs to be encapsulated to only run on those versions. Note that since version 14.0 is also the first version for iOS on Mac, you can safely assume that it cannot be on a Mac if the version is prior 14.0.

// Swift
var isiOSAppOnMac = false
if #available(iOS 14.0, *) {
    isiOSAppOnMac = ProcessInfo.processInfo.isiOSAppOnMac
}
print("\(isiOSAppOnMac ? "iOS app on Mac" : "not iOS on Mac")!")

Or if you prefer Objective-C:

// Objective-C
BOOL isiOSAppOnMac = false;
if (@available(iOS 14.0, *)) {
    isiOSAppOnMac = [NSProcessInfo processInfo].isiOSAppOnMac;
}
NSLog(@"%@", isiOSAppOnMac ? @"iOS app on Mac" : @"not iOS app on Mac");

Reference: Apple: Running Your iOS Apps on macOS

This code also checks if the app is running as a Mac Catalyst app.

var isiOSAppOnMac: Bool = {
#if targetEnvironment(macCatalyst)
    return true
#else
    if #available(iOS 14.0, *) {
        return ProcessInfo.processInfo.isiOSAppOnMac
    } else {
        return false
    }
#endif
}()

The simplest way:

struct Environment {
  static let isSimulator: Bool = {
    #if arch(i386) || arch(x86_64)
    return true
    #else
    return ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] != nil
    #endif
  }()
}

usage:

Environment.isSimulator

Your question has following subquestions.

  1. How to not allow my iOS app to be available on Mac when?

If you would like to limit your app to be only downloadable on iOS devices and not macOS devices then in the App Store Connect you can disable the Mac availability for your app. Learn more

  1. How to know if my app iOS is running under macOS powered by M1?

You have to get information about CPU and this question was already asked and has a good answer here

For checking if app is running in iOS mode on a Mac Apple Silicon (like M1), you have to check the new var available ONLY for iOS 14+ :

Objective-c :

if (@available(iOS 14.0, *) && [NSProcessInfo processInfo].isiOSAppOnMac) {
    // on Mac
}

Swift :

if #available(iOS 14.0, *), ProcessInfo.processInfo.isiOSAppOnMac {
    // on Mac
}
Related