【问题标题】:Swift generics class for device设备的 Swift 泛型类
【发布时间】:2021-08-03 09:37:34
【问题描述】:

假设我有一个静态函数isDeviceIpad
对于任何支持 iPad 的类,我都有带有“_iPad”后缀的子类,以及里面的所有 iPad 逻辑。
我使用classForDevice 函数为我当前的设备获取正确的类:

static private let iPadClassSuffix = "_iPad"

static func classForDevice() -> AnyClass? {
    var iPadClass: AnyClass?
    let moduleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
    let swiftClassName = moduleName+"."+String(describing: self)

    if isDeviceIpad {
        let iPadClassName = swiftClassName+iPadClassSuffix
        iPadClass = Bundle.main.classNamed(iPadClassName)
    }

    return iPadClass ?? Bundle.main.classNamed(swiftClassName)
}

现在我想将此函数转换为使用泛型,例如:
如果我的班级是 MyClass 而我的 iPad 班级是 MyClass_iPad

let myClass = MyClass.classForDevice().init(with parameters...)

应该为 iPhone 返回 MyClass 的实例,为 iPad 返回 MyClass_iPad 的实例。
有什么建议?也许使用协议?

【问题讨论】:

  • 听起来像 factory pattern 对我来说
  • 为什么不让MyClassMyClass_iPad 遵循相同的协议呢?然后,您可以调用方法并获取当时存储在内存中的任一方法的属性。
  • 你需要一个协议而不是我所看到的泛型。创建一个包含 MyClass 中所有公共属性和方法的协议,并声明 classForDevice 以返回该协议
  • 考虑:将 MyClassIpad 设为 MyClass 的子类,然后当您需要新建 MyClass 时,让它根据设备返回 MyClass 或 MyClassIpad,但作为 MyClass。不需要协议。
  • 鉴于 cmets 中提供的解决方案的多样性,我投票决定以固执己见的方式结束这个问题。如果您选择一条路径并尝试实施它,然后在遇到任何问题时返回一个新问题,这可能会更好。

标签: ios swift generics


【解决方案1】:

我最终为此创建了一个通用类:

class DeviceHandler<T: AnyObject> {
    static var classForDevice: T.Type {
        var iPadClass: T.Type?
        let iPadClassSuffix = "_iPad"
        let moduleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
        let swiftClassName = moduleName+"."+String(describing: T.self)

        if Utils.isDeviceIpad {
            let iPadClassName = swiftClassName+iPadClassSuffix
            iPadClass =  Bundle.main.classNamed(iPadClassName) as? T.Type
        }

        return iPadClass ?? T.self
    }
}

然后我像这样使用它:

let myClass = DeviceHandler<MyClass>.classForDevice.init(with parameters...)

编辑:将 classForDevice 更改为静态变量,因此我不需要创建 DeviceHandler 的实例

【讨论】:

  • 这……很奇怪。 (我没有投反对票)
  • 如果我能理解这段代码 sn-p 有意义的上下文,我会的。这很奇怪。切换设备类型通常是一种反模式,这只是在这个有缺陷的想法之上的几层反射/复杂性
  • @Alexander 主要思想是对不同的设备使用相同的逻辑,并进行细微的外观更改,例如在“_iPad”类上,您可能会覆盖组合布局的项目宽度或 AlertController 演示样式等行为,但保持两种设备的大部分代码结构相似。我想避免在我的类上检查isDeviceIpad,而是覆盖专用类上的行为
  • 我得到了这么多,但我看到了一些问题。一方面,您不应该真正根据设备是 iPad 还是 iPhone 来区分布局/UI。这只是错误。在 Slide Over 模式下运行的 iPad 应用程序与 iPhone 一样窄。您基于它是 iPad(认为 iPad = 大)做出的任何布局决定都会导致该模式下的界面很糟糕。分屏或将来可能添加的其他 iPad OS 功能也可能发生同样的事情
  • 所以也许这个例子是错误的,但有时你会有所不同,例如 AlertControllers 或模态演示样式。在一个班级上维护所有这些可能会很麻烦。我更喜欢在专用子类上覆盖逻辑,这样您就可以保持代码干净,并在一个地方管理所有设备专用代码。尤其是在为现有代码库添加 iPad 支持时。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 2017-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多