You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在iOS模拟器中模拟不同外形规格的设备?

搞定iOS模拟器下的设备型号判断难题

我太懂你这种处境了——想覆盖不同iOS设备的测试,但不可能把所有真机都买齐,模拟器绝对是救星,但之前用switch语句判断设备型号的逻辑到了模拟器就拉胯,毕竟模拟器本身的设备标识和它模拟的真机完全不是一回事,确实头疼。

先猜猜你之前大概是这么写的(基于sysctlbyname拿设备型号的常规操作):

func getDeviceModel() -> 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)))
    }
    
    switch identifier {
    case "iPhone14,2": return "iPhone 13 Pro"
    case "iPad13,1": return "iPad Air (4th gen)"
    // 一堆真机型号的case...
    case "x86_64", "arm64": return "Simulator"
    default: return identifier
    }
}

这种写法在真机上跑没问题,但模拟器只会返回x86_64(Intel Mac)或arm64(Apple Silicon Mac),根本没法知道你当前模拟的是哪款iPhone/iPad,测试不同设备布局的时候特别不方便。

给你个完美解决方案:获取模拟器模拟的真机型号

其实苹果在模拟器环境里悄悄留了个后门——一个叫SIMULATOR_MODEL_IDENTIFIER的环境变量,直接能拿到当前模拟设备的型号标识,和真机上的完全一致!我们可以把这个逻辑整合进去:

import UIKit

func getCurrentDeviceIdentifier() -> String {
    // 先判断是不是模拟器环境
    #if targetEnvironment(simulator)
        // 从环境变量里捞模拟的真机型号
        if let simModelID = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
            return simModelID
        }
        return "Unknown Simulator"
    #else
        // 真机环境下的常规型号获取逻辑
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { id, element in
            guard let val = element.value as? Int8, val != 0 else { return id }
            return id + String(UnicodeScalar(UInt8(val)))
        }
        return identifier
    #endif
}

// 然后用统一的switch来映射型号到设备名称
func getDeviceName() -> String {
    let deviceID = getCurrentDeviceIdentifier()
    
    switch deviceID {
    case "iPhone14,2": return "iPhone 13 Pro"
    case "iPhone15,3": return "iPhone 15 Pro"
    case "iPad13,1": return "iPad Air (4th Generation)"
    case "iPad17,1": return "iPad Pro 12.9-inch (6th Gen)"
    // 这里可以继续补充所有你需要支持的设备型号
    default: return deviceID
    }
}

为啥这方法好使?

  • 模拟器里,SIMULATOR_MODEL_IDENTIFIER会直接返回你当前模拟的设备型号(比如你选了iPhone 15 Pro模拟,就返回iPhone15,3),和真机上拿到的标识一模一样,这样你的switch语句不用单独写模拟器的case,一套逻辑通吃真机和模拟器。
  • #if targetEnvironment(simulator)做编译条件判断,真机环境下根本不会执行模拟器相关的代码,完全不影响性能。

额外小tip

如果你需要更新设备型号对应关系,苹果官方文档里有完整的列表,也可以找一些维护及时的开源设备型号库来批量导入,省得自己一个个加,毕竟苹果每年都出新机子嘛。

这样改完之后,不管你在真机还是模拟器上跑,都能准确识别出对应的设备型号,测试不同布局的时候就顺畅多啦~

内容的提问来源于stack exchange,提问作者iKK

火山引擎 最新活动