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).

所以,请告诉我,谢谢!


当前回答

不使用镜像也可以在Swift中获取设备名称。Swift可以在需要的地方自动将内容转换为指针。其实很简单:

/// Returns "iPhone1,1", etc.
var deviceName: String {
    var sysinfo = utsname()
    uname(&sysinfo)
    return String(cString: &sysinfo.machine.0)
}

(向这个被低估的答案致敬https://stackoverflow.com/a/43599474/843454)

其他回答

下面是它的代码(代码可能不包含所有设备的字符串,我和其他人在GitHub上维护相同的代码,所以请从那里获取最新的代码)

Objective-C: GitHub/DeviceUtil

吉hub /恶魔大师


#include <sys/types.h>
#include <sys/sysctl.h>

- (NSString*)hardwareDescription {
    NSString *hardware = [self hardwareString];
    if ([hardware isEqualToString:@"iPhone1,1"]) return @"iPhone 2G";
    if ([hardware isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
    if ([hardware isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
    if ([hardware isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
    if ([hardware isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
    if ([hardware isEqualToString:@"iPod1,1"]) return @"iPodTouch 1G";
    if ([hardware isEqualToString:@"iPod2,1"]) return @"iPodTouch 2G";
    if ([hardware isEqualToString:@"iPad1,1"]) return @"iPad";
    if ([hardware isEqualToString:@"iPad2,6"]) return @"iPad Mini";
    if ([hardware isEqualToString:@"iPad4,1"]) return @"iPad Air WIFI";
    //there are lots of other strings too, checkout the github repo
    //link is given at the top of this answer

    if ([hardware isEqualToString:@"i386"]) return @"Simulator";
    if ([hardware isEqualToString:@"x86_64"]) return @"Simulator";

    return nil;
}

- (NSString*)hardwareString {
    size_t size = 100;
    char *hw_machine = malloc(size);
    int name[] = {CTL_HW,HW_MACHINE};
    sysctl(name, 2, hw_machine, &size, NULL, 0);
    NSString *hardware = [NSString stringWithUTF8String:hw_machine];
    free(hw_machine);
    return hardware;
}

兼容Swift 3

// MARK: - UIDevice Extension -

private let DeviceList = [
/* iPod 5 */          "iPod5,1": "iPod Touch 5",
/* iPhone 4 */        "iPhone3,1":  "iPhone 4", "iPhone3,2": "iPhone 4", "iPhone3,3": "iPhone 4",
/* iPhone 4S */       "iPhone4,1": "iPhone 4S",
/* iPhone 5 */        "iPhone5,1": "iPhone 5", "iPhone5,2": "iPhone 5",
/* iPhone 5C */       "iPhone5,3": "iPhone 5C", "iPhone5,4": "iPhone 5C",
/* iPhone 5S */       "iPhone6,1": "iPhone 5S", "iPhone6,2": "iPhone 5S",
/* iPhone 6 */        "iPhone7,2": "iPhone 6",
/* iPhone 6 Plus */   "iPhone7,1": "iPhone 6 Plus",
/* iPhone 6S */       "iPhone8,1": "iPhone 6S",
/* iPhone 6S Plus */  "iPhone8,2": "iPhone 6S Plus",
/* iPhone SE */       "iPhone8,4": "iPhone SE",
/* iPhone 7 */        "iPhone9,1": "iPhone 7",
/* iPhone 7 */        "iPhone9,3": "iPhone 7",
/* iPhone 7 Plus */   "iPhone9,2": "iPhone 7 Plus",
/* iPhone 7 Plus */   "iPhone9,4": "iPhone 7 Plus",
/* iPad 2 */          "iPad2,1": "iPad 2", "iPad2,2": "iPad 2", "iPad2,3": "iPad 2", "iPad2,4": "iPad 2",
/* iPad 3 */          "iPad3,1": "iPad 3", "iPad3,2": "iPad 3", "iPad3,3":     "iPad 3",
/* iPad 4 */          "iPad3,4": "iPad 4", "iPad3,5": "iPad 4", "iPad3,6": "iPad 4",
/* iPad Air */        "iPad4,1": "iPad Air", "iPad4,2": "iPad Air", "iPad4,3": "iPad Air",
/* iPad Air 2 */      "iPad5,1": "iPad Air 2", "iPad5,3": "iPad Air 2", "iPad5,4": "iPad Air 2",
/* iPad Mini */       "iPad2,5": "iPad Mini 1", "iPad2,6": "iPad Mini 1", "iPad2,7": "iPad Mini 1",
/* iPad Mini 2 */     "iPad4,4": "iPad Mini 2", "iPad4,5": "iPad Mini 2", "iPad4,6": "iPad Mini 2",
/* iPad Mini 3 */     "iPad4,7": "iPad Mini 3", "iPad4,8": "iPad Mini 3", "iPad4,9": "iPad Mini 3",
/* iPad Pro 12.9 */   "iPad6,7": "iPad Pro 12.9", "iPad6,8": "iPad Pro 12.9",
/* iPad Pro  9.7 */   "iPad6,3": "iPad Pro 9.7", "iPad6,4": "iPad Pro 9.7",
/* Simulator */       "x86_64": "Simulator", "i386": "Simulator"
]

extension UIDevice {

    static var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)

        let machine = systemInfo.machine
        let mirror = Mirror(reflecting: machine)

        var identifier = ""

        for child in mirror.children {
            if let value = child.value as? Int8, value != 0 {
                identifier += String(UnicodeScalar(UInt8(value)))
            }
        }
        return DeviceList[identifier] ?? identifier
    }

    static var isIphone4: Bool {
        return modelName == "iPhone 5" || modelName == "iPhone 5C" || modelName == "iPhone 5S" || UIDevice.isSimulatorIPhone4
    }

    static var isIphone5: Bool {
        return modelName == "iPhone 4S" || modelName == "iPhone 4" || UIDevice.isSimulatorIPhone5
    }

    static var isIphone6: Bool {
        return modelName == "iPhone 6" || UIDevice.isSimulatorIPhone6
    }
    static var isIphone6Plus: Bool {
        return modelName == "iPhone 6 Plus" || UIDevice.isSimulatorIPhone6Plus
    }

    static var isIpad: Bool {
        if UIDevice.current.model.contains("iPad") {
            return true
        }
        return false
    }

    static var isIphone: Bool {
        return !self.isIpad
    }

    /// Check if current device is iPhone4S (and earlier) relying on screen heigth
    static var isSimulatorIPhone4: Bool {
        return UIDevice.isSimulatorWithScreenHeigth(480)
    }

    /// Check if current device is iPhone5 relying on screen heigth
    static var isSimulatorIPhone5: Bool {
        return UIDevice.isSimulatorWithScreenHeigth(568)
    }

    /// Check if current device is iPhone6 relying on screen heigth
    static var isSimulatorIPhone6: Bool {
        return UIDevice.isSimulatorWithScreenHeigth(667)
    }

    /// Check if current device is iPhone6 Plus relying on screen heigth
    static var isSimulatorIPhone6Plus: Bool {
        return UIDevice.isSimulatorWithScreenHeigth(736)
    }

    private static func isSimulatorWithScreenHeigth(_ heigth: CGFloat) -> Bool {
        let screenSize: CGRect = UIScreen.main.bounds
        return modelName == "Simulator" && screenSize.height == heigth
    }

}

虽然这个问题在2012年就被提出了,但苹果仍然没有给出将设备模式标识符转换为设备名称的方法。 有很多答案依赖于硬编码这些名称,不幸的是,当苹果发布新设备时,这些名称很快就过时了。

我们需要的是一种方法来获得一个不断更新的列表,它就在这里:https://github.com/ptrkstr/Devices

每次添加新设备时,这个Swift包都会更新,你所需要做的就是更新你的依赖项来获得它们。

以下是Aniruddh基于uname的方法的现代版本,它不依赖于Mirror,应该适用于Swift 4.2及更高版本:

import UIKit

extension UIDevice {
  var machineName: String {
    var info = utsname()
    return withUnsafeMutablePointer(to: &info) { info in
      // We could alternatively return nil here, or handle
      // errors some other way.
      guard uname(info) == 0 else { return model }
      let offset = MemoryLayout.offset(of: \utsname.machine)!
      let machine = UnsafeRawPointer(info).advanced(by: offset).assumingMemoryBound(to: CChar.self)
      return String(cString: machine)
    }
  }
}

如果你有一个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()函数)。