I was wondering if it's possible to determine what kind of iPhone (for example) the currentdevice is? I know it's possible to get the model through NSString *deviceType = [[UIDevice currentDevice] model]; which will just return whether I have an "iPhone" or an "iPod", BUT I was wondering if it's possible to detect/know if I have an iPhone 3GS vs. and iPhone 4 vs. an iPhone 4S (in actuality, all I really want to do is determine if I have a 3G or not, because I'm doing fairly graphics intensive stuff).

所以,请告诉我,谢谢!


当前回答

这个解决方案适用于物理设备和iOS模拟器,模拟器返回的模型与物理设备返回的模型相同。iPhone X (GSM)为iPhone10,6,而不是“x86_64”。

定义- Swift 4:

import UIKit

extension UIDevice {
    var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        if let value = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
            return value
        } else {
            return identifier
        }
    }
}

用法:

print(UIDevice.current.modelName)

其他回答

Swift 4或更高版本

extension UIDevice {
    var modelName: String {
        if let modelName = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] { return modelName }
        var info = utsname()
        uname(&info)
        return String(String.UnicodeScalarView(
                   Mirror(reflecting: info.machine)
                    .children
                    .compactMap {
                        guard let value = $0.value as? Int8 else { return nil }
                        let unicode = UnicodeScalar(UInt8(value))
                        return unicode.isASCII ? unicode : nil
                    }))
    }
}

UIDevice.current.modelName   // "iPad6,4"
#import <sys/utsname.h>

#define HARDWARE @{@"i386": @"Simulator",@"x86_64": @"Simulator",@"iPod1,1": @"iPod Touch",@"iPod2,1": @"iPod Touch 2nd Generation",@"iPod3,1": @"iPod Touch 3rd Generation",@"iPod4,1": @"iPod Touch 4th Generation",@"iPhone1,1": @"iPhone",@"iPhone1,2": @"iPhone 3G",@"iPhone2,1": @"iPhone 3GS",@"iPhone3,1": @"iPhone 4",@"iPhone4,1": @"iPhone 4S",@"iPhone5,1": @"iPhone 5",@"iPhone5,2": @"iPhone 5",@"iPhone5,3": @"iPhone 5c",@"iPhone5,4": @"iPhone 5c",@"iPhone6,1": @"iPhone 5s",@"iPhone6,2": @"iPhone 5s",@"iPad1,1": @"iPad",@"iPad2,1": @"iPad 2",@"iPad3,1": @"iPad 3rd Generation ",@"iPad3,4": @"iPad 4th Generation ",@"iPad2,5": @"iPad Mini",@"iPad4,4": @"iPad Mini 2nd Generation - Wifi",@"iPad4,5": @"iPad Mini 2nd Generation - Cellular",@"iPad4,1": @"iPad Air 5th Generation - Wifi",@"iPad4,2": @"iPad Air 5th Generation - Cellular"}

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    struct utsname systemInfo;
    uname(&systemInfo);
    NSLog(@"hardware: %@",[HARDWARE objectForKey:[NSString stringWithCString: systemInfo.machine encoding:NSUTF8StringEncoding]]);
}

这个解决方案适用于物理设备和iOS模拟器,模拟器返回的模型与物理设备返回的模型相同。iPhone X (GSM)为iPhone10,6,而不是“x86_64”。

定义- Swift 4:

import UIKit

extension UIDevice {
    var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        if let value = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
            return value
        } else {
            return identifier
        }
    }
}

用法:

print(UIDevice.current.modelName)

我优化了NicolasMiari的实现,并添加了模拟器,在这里:

+ (NSString*)deviceName {

  static NSDictionary* deviceNamesByCode = nil;
  static NSString* deviceName = nil;

  if (deviceName) {
    return deviceName;
  }

  deviceNamesByCode = @{
    @"i386"      :@"Simulator",
    @"iPod1,1"   :@"iPod Touch",      // (Original)
    @"iPod2,1"   :@"iPod Touch",      // (Second Generation)
    @"iPod3,1"   :@"iPod Touch",      // (Third Generation)
    @"iPod4,1"   :@"iPod Touch",      // (Fourth Generation)
    @"iPhone1,1" :@"iPhone",          // (Original)
    @"iPhone1,2" :@"iPhone",          // (3G)
    @"iPhone2,1" :@"iPhone",          // (3GS)
    @"iPad1,1"   :@"iPad",            // (Original)
    @"iPad2,1"   :@"iPad 2",          //
    @"iPad3,1"   :@"iPad",            // (3rd Generation)
    @"iPhone3,1" :@"iPhone 4",        //
    @"iPhone4,1" :@"iPhone 4S",       //
    @"iPhone5,1" :@"iPhone 5",        // (model A1428, AT&T/Canada)
    @"iPhone5,2" :@"iPhone 5",        // (model A1429, everything else)
    @"iPad3,4"   :@"iPad",            // (4th Generation)
    @"iPad2,5"   :@"iPad Mini",       // (Original)
    @"iPhone5,3" :@"iPhone 5c",       // (model A1456, A1532 | GSM)
    @"iPhone5,4" :@"iPhone 5c",       // (model A1507, A1516, A1526 (China), A1529 | Global)
    @"iPhone6,1" :@"iPhone 5s",       // (model A1433, A1533 | GSM)
    @"iPhone6,2" :@"iPhone 5s",       // (model A1457, A1518, A1528 (China), A1530 | Global)
    @"iPad4,1"   :@"iPad Air",        // 5th Generation iPad (iPad Air) - Wifi
    @"iPad4,2"   :@"iPad Air",        // 5th Generation iPad (iPad Air) - Cellular
    @"iPad4,4"   :@"iPad Mini",       // (2nd Generation iPad Mini - Wifi)
    @"iPad4,5"   :@"iPad Mini"        // (2nd Generation iPad Mini - Cellular)
  };

  struct utsname systemInfo;
  uname(&systemInfo);
  NSString* code = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];

  deviceName = [deviceNamesByCode objectForKey:code];

  if (!deviceName) {
    // Not found in database. At least guess main device type from string contents:

    if ([code rangeOfString:@"iPod"].location != NSNotFound) {
      deviceName = @"iPod Touch";
    } else if([code rangeOfString:@"iPad"].location != NSNotFound) {
      deviceName = @"iPad";
    } else if([code rangeOfString:@"iPhone"].location != NSNotFound){
      deviceName = @"iPhone";
    } else {
      deviceName = @"Simulator";
    }
  }

  return deviceName;
}

```

如果你有一个plist设备(例如在https://stackoverflow.com/a/17655825/849616中由@Tib维护)来处理Swift 3,你会使用:

extension UIDevice {
    /// Fetches the information about the name of the device.
    ///
    /// - Returns: Should return meaningful device name, if not found will return device system code.
    public static func modelName() -> String {
        let physicalName = deviceSystemCode()
        if let deviceTypes = deviceTypes(), let modelName = deviceTypes[physicalName] as? String {
            return modelName
        }
        return physicalName
    }
}

private extension UIDevice {
    /// Fetches from system the code of the device
    static func deviceSystemCode() -> String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        return identifier
    }

    /// Fetches the plist entries from plist maintained in https://stackoverflow.com/a/17655825/849616
    ///
    /// - Returns: A dictionary with pairs of deviceSystemCode <-> meaningfulDeviceName.
    static func deviceTypes() -> NSDictionary? {
        if let fileUrl = Bundle.main.url(forResource: "your plist name", withExtension: "plist"),
            let configurationDictionary = NSDictionary(contentsOf: fileUrl) {
            return configurationDictionary
        }
        return nil
    }
}

稍后您可以使用UIDevice.modelName()调用它。

额外的荣誉归于@Tib(用于plist), @Aniruddh Joshi(用于deviceSystemCode()函数)。