在Mac应用程序中,我如何以编程方式检测(在运行时)应用程序当前是否运行在带有英特尔或苹果硅处理器的Mac上?
在Objective-C中,可以使用systemuname
函数。这相当于来自壳层的uname -m
。
#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];
}
或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)
}
对于最新型号的Intel mac,返回x86_64
。对于Apple Silicon,它返回arm64
。
解决方案兼容Xcode 14及更新版本
我们检索utsname.machine
并将其与"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"或";i386"对于英特尔
MacOS 12+更新
Todd的答案会崩溃当一个应用程序链接到macOS 12.5 SDK,因为sysInfo.machine
字段不是一个以空结束的字符串,这显然现在由String(cString:encoding:)
强制执行。
这是一个可以工作的更新版本:
///
/// 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: "