iosswift

iOS how to get CPU architecture given NXGetLocalArchInfo has been deprecated?


I am working on a "device info" app and it shows the CPU architecture. I have been using this code which works fine.

  func getArchitecture() -> String? {
    guard
      let info = NXGetLocalArchInfo(),
      let string = info.pointee.description
    else { return nil }
    return String(utf8String: string)
  }
  

The NXGetLocalArchInfo function has been deprecated in iOS 16, and I don't know what to use instead.

Edit: After some research, it looks like the new API should be macho_arch_name_for_mach_header: https://github.com/firebase/firebase-ios-sdk/commit/19c1b15f7c012b0633eb74fd2effd961c88d28a3

However, I don't know how to write it in Swift. Please help.


Solution

  • The Objective-C header file <mach-o/arch.h> shows that NXGetLocalArchInfo is deprecated and you should use macho_arch_name_for_mach_header(). macho_arch_name_for_mach_header() can be found in <macho-o.utils.h>.

    Unfortunately, the MachO module (in both Objective-C and Swift) does not include the utils submodule.

    One solution would be to write a simple Objective-C class that can import <macho-o.utils.h> and call macho_arch_name_for_mach_header(). Then this helper class can be called from Swift.

    Here's an example implementation.

    Start by adding a Cocoa Touch Class to your project. On the options screen for the new file, choose Objective-C as the language. Enter a name such as ArchInfo for the class and have it subclass NSObject.

    If this is the first Objective-C code you've added to the Swift project, you will be prompted about adding a bridging header file. Choose the option to have this added. A file named something like Project-Bridging-Header.h will be added to the project.

    Add the following line to the new (or your existing) bridging header file:

    #import "ArchInfo.h" // Or whatever name you gave the new class
    

    Update the contents of ArchInfo.h as follows:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface ArchInfo : NSObject
    
    @property (nonatomic, nullable, readonly, class) NSString *archName;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    Update ArchInfo.m as follows:

    #import "ArchInfo.h"
    #import <mach-o/utils.h>
    
    @implementation ArchInfo
    
    + (NSString *)archName {
        const char* name = macho_arch_name_for_mach_header(NULL);
    
        return name ? [NSString stringWithCString:name encoding:NSUTF8StringEncoding] : nil;
    }
    
    @end
    

    Then in some Swift file you can do:

    print("Arch name: \(ArchInfo.archName ?? "Unknown")")
    

    When run on in an iOS simulator on my Intel Mac, the output is:

    Arch name: x86_64