【问题标题】:How to Simulate different form-factors in iOS?如何在 iOS 中模拟不同的外形尺寸?
【发布时间】:2018-10-11 10:15:48
【问题描述】:

通常,我想针对不同的设备测试我的 iOS 应用程序。由于我没有钱购买所有设备,所以我使用模拟器这样做:)

通常,对于 Apple 产品的不同外形尺寸,代码看起来会略有不同。因此,我想出了以下开关案例(见下文...)以编程方式区分设备。

switch-case 非常适合实际的硬件设备 - 但它仍然是使用模拟器的糟糕解决方案。

模拟器是它自己的设备!如果我更改为具有不同外形的模拟器目标,我需要在每个 switch-case 中取消注释/注释!

是否有更好的解决方案以编程方式更好地处理模拟器及其外形?

switch UIDevice.current.modelName {

    // Here there is still the need to uncomment/comment the Devices.Simulator
    // for any new form-factor that is being simulated....

    // as an example: If simulating an iPhone-8S then the Devices.Simulator needs to be uncommented in the according switch-case...

    case Devices.IPhone5, Devices.IPhone5S, Devices.IPhone5C: //, Devices.Simulator:
        print("do whatever...")
    case Devices.IPhone6, Devices.IPhone6S, Devices.IPhone7, Devices.IPhone8: //, Devices.Simulator:
        print("do whatever...")
    case Devices.IPhone6Plus, Devices.IPhone6SPlus, Devices.IPhone7Plus, Devices.IPhone8Plus, Devices.Simulator:
        print("do whatever...")
    case Devices.IPhoneX: //, Devices.Simulator:
        print("do whatever...")
    default:
        print("do whatever...")
}

当然,在您的代码库中的某处有以下内容:

public enum Devices: String {
    case IPodTouch5
    case IPodTouch6
    case IPhone4
    case IPhone4S
    case IPhone5
    case IPhone5C
    case IPhone5S
    case IPhone6
    case IPhone6Plus
    case IPhone6S
    case IPhone6SPlus
    case IPhone7
    case IPhone7Plus
    case IPhoneSE
    case IPhone8
    case IPhone8Plus
    case IPhoneX
    case IPad2
    case IPad3
    case IPad4
    case IPad5
    case IPadAir
    case IPadAir2
    case IPadMini
    case IPadMini2
    case IPadMini3
    case IPadMini4
    case IPadPro_9_7
    case IPadPro_12_9
    case IPadPro_12_9_2ndGen
    case IPadPro_10_5
    case AppleTV_5_3
    case AppleTV_6_2
    case HomePod
    case Simulator
    case Other
}

还有……

public extension UIDevice {

    public var modelName: Devices {
        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 "iPod5,1":                                 return Devices.IPodTouch5
        case "iPod7,1":                                 return Devices.IPodTouch6
        case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return Devices.IPhone4
        case "iPhone4,1":                               return Devices.IPhone4S
        case "iPhone5,1", "iPhone5,2":                  return Devices.IPhone5
        case "iPhone5,3", "iPhone5,4":                  return Devices.IPhone5C
        case "iPhone6,1", "iPhone6,2":                  return Devices.IPhone5S
        case "iPhone7,2":                               return Devices.IPhone6
        case "iPhone7,1":                               return Devices.IPhone6Plus
        case "iPhone8,1":                               return Devices.IPhone6S
        case "iPhone8,2":                               return Devices.IPhone6SPlus
        case "iPhone9,1", "iPhone9,3":                  return Devices.IPhone7
        case "iPhone9,2", "iPhone9,4":                  return Devices.IPhone7Plus
        case "iPhone8,4":                               return Devices.IPhoneSE
        case "iPhone10,1", "iPhone10,4":                return Devices.IPhone8
        case "iPhone10,2", "iPhone10,5":                return Devices.IPhone8Plus
        case "iPhone10,3", "iPhone10,6":                return Devices.IPhoneX
        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return Devices.IPad2
        case "iPad3,1", "iPad3,2", "iPad3,3":           return Devices.IPad3
        case "iPad3,4", "iPad3,5", "iPad3,6":           return Devices.IPad4
        case "iPad4,1", "iPad4,2", "iPad4,3":           return Devices.IPadAir
        case "iPad5,3", "iPad5,4":                      return Devices.IPadAir2
        case "iPad6,11", "iPad6,12":                    return Devices.IPad5
        case "iPad2,5", "iPad2,6", "iPad2,7":           return Devices.IPadMini
        case "iPad4,4", "iPad4,5", "iPad4,6":           return Devices.IPadMini2
        case "iPad4,7", "iPad4,8", "iPad4,9":           return Devices.IPadMini3
        case "iPad5,1", "iPad5,2":                      return Devices.IPadMini4
        case "iPad6,3", "iPad6,4":                      return Devices.IPadPro_9_7
        case "iPad6,7", "iPad6,8":                      return Devices.IPadPro_12_9
        case "iPad7,1", "iPad7,2":                      return Devices.IPadPro_12_9_2ndGen
        case "iPad7,3", "iPad7,4":                      return Devices.IPadPro_10_5
        case "AppleTV5,3":                              return Devices.AppleTV_5_3
        case "AppleTV6,2":                              return Devices.AppleTV_6_2
        case "AudioAccessory1,1":                       return Devices.HomePod
        case "i386", "x86_64":                          return Devices.Simulator
        default:                                        return Devices.Other
        }
    }
}

【问题讨论】:

  • 这取决于您要达到的目标。 Apple 定义尺寸类以管理布局问题:bignerdranch.com/blog/designing-for-size-classes-in-ios
  • 请注意,您可以在模拟器中运行时检索(模拟的)iPhone模型:stackoverflow.com/a/30075200/1187415
  • 大多数情况下,我想区分 iPhoneSE 大小的设备和 iPhone6/7/8 大小的设备。如果您向我展示了如何使用 size-classes 来解决这个问题,那么我很高兴不再自己在代码中手动执行它! (......但直到今天,我还没有看到区分这两种外形尺寸的解决方案 [i.s. iPhoneSE 与 iPhone6/7/8])!!
  • 你为什么要区分它们呢?你还没有提到你想要达到的目标。
  • 它没有,它们在纵向上都很紧凑,但你应该设计一个可以在两者之间适应的布局,这就是 AutoLayout 的重点。有时您必须做出妥协(这应该与每个用户的数量有关),这是完全正常的。你的方法很糟糕,它不是一个开始的未来证明,但它也是不必要的和过度设计的。

标签: swift xcode model device simulator


【解决方案1】:

我找到了更好的解决方案,请参阅“借助 Martin R 的输入,....”

【讨论】:

    【解决方案2】:

    通过Martin R 的输入,我现在有了一个很好的解决方案,在区分 iOS 设备的外形尺寸(无论是硬件还是模拟器)时,用户无需在代码中手动输入一些内容! [当然,不包括未来新的 Apple 设备...]

    最重要的是:它也是区分 iPhoneSE 和 iPhone6/7/8 外形尺寸的解决方案!

    struct AppConstants {
    
        // feature flags
        struct FEATUREFLAG {
    
            static let DEVICE_MODEL_NAME = { () -> Devices in
                switch UIDevice.current.modelName {
                case Devices.Simulator:
                    // set featureFlag for different form-factors to be simulated...
                    return UIDevice.current.simulatorModelName
                default:
                    // set featureFlag for different form-factors on actual device...
                    return UIDevice.current.modelName
                }
            }()
        }
    }
    

    以及设备扩展名的变化:

    public extension UIDevice {
    
        public var modelName: Devices {
            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 self.getDeviceFromIdentifier(identifier: identifier)
        }
    
        public var simulatorModelName: Devices {
    
            if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { return getDeviceFromIdentifier(identifier: simulatorModelIdentifier) }
            var sysinfo = utsname()
            uname(&sysinfo) // ignore return value
            return getDeviceFromIdentifier(identifier: String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters))
        }
    
        private func getDeviceFromIdentifier(identifier: String) -> Devices {
            switch identifier {
            case "iPod5,1":                                 return Devices.IPodTouch5
            case "iPod7,1":                                 return Devices.IPodTouch6
            case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return Devices.IPhone4
            case "iPhone4,1":                               return Devices.IPhone4S
            case "iPhone5,1", "iPhone5,2":                  return Devices.IPhone5
            case "iPhone5,3", "iPhone5,4":                  return Devices.IPhone5C
            case "iPhone6,1", "iPhone6,2":                  return Devices.IPhone5S
            case "iPhone7,2":                               return Devices.IPhone6
            case "iPhone7,1":                               return Devices.IPhone6Plus
            case "iPhone8,1":                               return Devices.IPhone6S
            case "iPhone8,2":                               return Devices.IPhone6SPlus
            case "iPhone9,1", "iPhone9,3":                  return Devices.IPhone7
            case "iPhone9,2", "iPhone9,4":                  return Devices.IPhone7Plus
            case "iPhone8,4":                               return Devices.IPhoneSE
            case "iPhone10,1", "iPhone10,4":                return Devices.IPhone8
            case "iPhone10,2", "iPhone10,5":                return Devices.IPhone8Plus
            case "iPhone10,3", "iPhone10,6":                return Devices.IPhoneX
            case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return Devices.IPad2
            case "iPad3,1", "iPad3,2", "iPad3,3":           return Devices.IPad3
            case "iPad3,4", "iPad3,5", "iPad3,6":           return Devices.IPad4
            case "iPad4,1", "iPad4,2", "iPad4,3":           return Devices.IPadAir
            case "iPad5,3", "iPad5,4":                      return Devices.IPadAir2
            case "iPad6,11", "iPad6,12":                    return Devices.IPad5
            case "iPad2,5", "iPad2,6", "iPad2,7":           return Devices.IPadMini
            case "iPad4,4", "iPad4,5", "iPad4,6":           return Devices.IPadMini2
            case "iPad4,7", "iPad4,8", "iPad4,9":           return Devices.IPadMini3
            case "iPad5,1", "iPad5,2":                      return Devices.IPadMini4
            case "iPad6,3", "iPad6,4":                      return Devices.IPadPro_9_7
            case "iPad6,7", "iPad6,8":                      return Devices.IPadPro_12_9
            case "iPad7,1", "iPad7,2":                      return Devices.IPadPro_12_9_2ndGen
            case "iPad7,3", "iPad7,4":                      return Devices.IPadPro_10_5
            case "AppleTV5,3":                              return Devices.AppleTV_5_3
            case "AppleTV6,2":                              return Devices.AppleTV_6_2
            case "AudioAccessory1,1":                       return Devices.HomePod
            case "i386", "x86_64":                          return Devices.Simulator
            default:                                        return Devices.Other
            }
        }
    }
    

    还有:

    public enum Devices: String {
        case IPodTouch5
        case IPodTouch6
        case IPhone4
        case IPhone4S
        case IPhone5
        case IPhone5C
        case IPhone5S
        case IPhone6
        case IPhone6Plus
        case IPhone6S
        case IPhone6SPlus
        case IPhone7
        case IPhone7Plus
        case IPhoneSE
        case IPhone8
        case IPhone8Plus
        case IPhoneX
        case IPad2
        case IPad3
        case IPad4
        case IPad5
        case IPadAir
        case IPadAir2
        case IPadMini
        case IPadMini2
        case IPadMini3
        case IPadMini4
        case IPadPro_9_7
        case IPadPro_12_9
        case IPadPro_12_9_2ndGen
        case IPadPro_10_5
        case AppleTV_5_3
        case AppleTV_6_2
        case HomePod
        case Simulator
        case Other
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 2020-12-26
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      相关资源
      最近更新 更多