In a Mac app, how can I programmatically detect (at runtime) whether the app is currently running on a Mac with an Intel or Apple Silicon processor?
Asked
Active
Viewed 1,962 times
3
-
Objective C or Swift? You tagged both. – Raptor Oct 19 '21 at 03:37
3 Answers
5
In Objective-C, you can use the system uname
function. This is equivalent to uname -m
from the shell.
#include <sys/utsname.h>
NSString *GetMachineHardwareName(void) {
struct utsname sysinfo;
int retVal = uname(&sysinfo);
if (EXIT_SUCCESS != retVal) return nil;
return [NSString stringWithUTF8String:sysinfo.machine];
}
or in Swift
func GetMachineHardwareName() -> String? {
var sysInfo = utsname()
let retVal = uname(&sysInfo)
guard retVal == EXIT_SUCCESS else { return nil }
return String(cString: &sysInfo.machine.0, encoding: .utf8)
}
For late-model Intel Macs, this returns x86_64
. For Apple Silicon, it returns arm64
.

Todd Ditchendorf
- 11,217
- 14
- 69
- 123
-
-
2I edited the answer to include a Swift version that works in Swift 5.5 at least. – Scott Thompson Oct 19 '21 at 04:45
-
Take care that it will give x84_64 as a result for an executable built for x86, non universal binary, eventhough the hardware is apple silicon. One have to use proc_translated to identify that properly. Please check https://stackoverflow.com/questions/66256300/c-c-code-to-have-different-execution-block-on-m1-and-intel/72526494#72526494 (it is C++ version, but it gives the idea) – Titus Jun 07 '22 at 10:54
-
1`String(cString: &sysInfo.machine.0, encoding: .utf8)` will crash with Xcode14 and newer. – Cœur Aug 04 '22 at 08:00
3
Solution compatible with Xcode 14 and newer.
We retrieve utsname.machine
and compare it to "arm64":
extension utsname {
static var sMachine: String {
var utsname = utsname()
uname(&utsname)
return withUnsafePointer(to: &utsname.machine) {
$0.withMemoryRebound(to: CChar.self, capacity: Int(_SYS_NAMELEN)) {
String(cString: $0)
}
}
}
static var isAppleSilicon: Bool {
sMachine == "arm64"
}
}
- "arm64" for Apple Silicon
- "x86_64" or "i386" for Intel

Cœur
- 37,241
- 25
- 195
- 267
2
Update For MacOS 12+
Todd's answer will crash when an app is linked against the macOS 12.5 SDK because the sysInfo.machine
field is not a null-terminated string and that's apparently now enforced by String(cString:encoding:)
.
Here's an updated version that will work:
///
/// Determines the architecture of the Mac on which we're running. Returns `arm64` for Apple Silicon
/// and `x86_64` for Intel-based Macs or `nil` if the system call fails.
///
func getMachineHardwareName() -> String?
{
var sysInfo = utsname()
let retVal = uname(&sysInfo)
var finalString: String? = nil
if retVal == EXIT_SUCCESS
{
let bytes = Data(bytes: &sysInfo.machine, count: Int(_SYS_NAMELEN))
finalString = String(data: bytes, encoding: .utf8)
}
// _SYS_NAMELEN will include a billion null-terminators. Clear those out so string comparisons work as you expect.
return finalString?.trimmingCharacters(in: CharacterSet(charactersIn: "\0"))
}

Bryan
- 4,628
- 3
- 36
- 62
-
You should use prefix(while:) to extract everything until the null terminator instead of trimming. Unless its just a couple of null terminators and not a billion. – oxygen Jul 07 '23 at 10:36