根据 iOS 版本使用类的不同实现?

Ten*_*Jay 4 ios swift availability

iOS 11 最近添加了一个我想使用的新功能,但我仍然需要支持旧版本的 iOS。有没有办法两次编写同一个类,让较新版本的 iOS 使用该类的一个版本,而较旧版本的 iOS 使用另一个?

(注意:最初我使用过if #available(iOS 11, *)但我不得不在很多地方使用它,我认为如果可能的话,拥有 2 个版本的类会更干净。也许有一种使用 @availble 的方法?我专注于使用 @可用而不是预编译器#IFDEF 的东西,因为现在似乎“可用”标签是在 Swift 中执行此操作的首选方式?)

小智 7

protocol Wrapper {

}

extension Wrapper {
    static func instantiate(parametersAB: Any*) -> Wrapper{
        if #available(iOS 11.0, *) {
            return A(parametersA)
        } else {
            return B(parametersB)
        }
    }
}

@available(iOS 11.0,*)
class A: Wrapper {
    //Use new feature of iOS 11
    init(parametersA: Any*) {
      ...
    }
}

class B: Wrapper {
    //Fallback
    init(parametersB: Any*) {
      ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过调用来获取实例Wrapper.instationate(params),这样您就可以忘记其余代码中的检查,并在可能的情况下使用新功能。

只有当您可以为两个类建立相同的接口(即使它是该方法的虚拟版本)时,此解决方案才有可能。


Vik*_*ica 5

高质量的代码遵循几个原则。其中一个是单一责任原则,它规定一个类应该只有一个责任,或者 \xe2\x80\x94 正如 Bob 叔叔所说的 \xe2\x80\x94 一个类应该只有一个改变的原因。
\n另一个原则是依赖倒置原则:一个类不应该依赖于较低级别的类,而应该依赖于这些较低级别的类实现的抽象(协议)。这也意味着所有依赖项都必须传递到使用它们的类中。

\n

适用于您的问题的一种解决方案可能是:

\n
    \n
  1. 视图控制器有一个定义为协议的数据源属性。
  2. \n
  3. 有几个类实现了此协议,每个类针对不同的 iOS 版本。
  4. \n
  5. 存在一个类,其唯一的准备就是选择正确的版本。这个版本选择可以通过多种方式完成,我坚持使用#available
  6. \n
\n

数据源协议:

\n
protocol ViewControllerDataSourcing: class {\n    var text:String { get }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

及其实现:

\n
class ViewControllerDataSourceIOS10: ViewControllerDataSourcing {\n    var text: String {\n        return "This is iOS 10"\n    }\n}\n\nclass ViewControllerDataSourceIOS11: ViewControllerDataSourcing {\n    var text: String {\n        return "This is iOS 11"\n    }\n}\n\nclass ViewControllerDataSourceIOSUnknown: ViewControllerDataSourcing {\n    var text: String {\n        return "This is iOS Unknown"\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

选择正确版本类的类:

\n
class DataSourceSelector{\n    class func dataSource() -> ViewControllerDataSourcing {\n        if #available(iOS 11, *) {\n            return ViewControllerDataSourceIOS11()\n        }\n        if #available(iOS 10, *) {\n            return ViewControllerDataSourceIOS10()\n        }\n        return ViewControllerDataSourceIOSUnknown()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

最后是视图控制器

\n
class ViewController: UIViewController {\n\n    var dataSource: ViewControllerDataSourcing?\n    \n    @IBOutlet weak var label: UILabel!\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        self.dataSource = DataSourceSelector.dataSource()\n        label.text = dataSource?.text\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个非常简单的示例,应该突出显示负责的不同组件。

\n


mat*_*att 0

“一个类的两个版本”听起来像是一个基类和两个子类。您可以在运行时根据系统版本通过查询 ProcessInfo 来实例化所需的子类。