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

时间:2017-09-07 16:40:17

标签: ios swift availability

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

(注意:最初我使用if #available(iOS 11, *)但我必须在很多地方使用它,我认为如果可能的话,有2个版本的课程会更干净。也许在那里&#39;以某种方式使用@avail的方式?我专注于使用@available而不是预编译#IFDEF的东西,因为看起来&#34;可用的#34;标签是现在在Swift中执行它的首选方式?)< / em>的

3 个答案:

答案 0 :(得分:3)

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*) {
      ...
    }
}

现在,您可以通过调用Wrapper.instationate(params)来获取实例,然后忘记检查其余代码,并尽可能使用新功能。

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

答案 1 :(得分:1)

高质量的代码遵循几个原则。一个是单一责任原则,即一个班级应该只有一个责任,或者 - 正如鲍勃叔叔所说的 - 一个班级应该只有一个原因可以改变。
另一个原则是依赖性倒置原则:一个类不应该依赖于较低级别的类,而应该依赖于这些较低级别类实现的抽象(协议)。这也意味着必须将所有依赖项传递给使用它们的类。

在您的问题上应用一个解决方案可能是:

  1. 视图控制器具有定义为协议的数据源属性。
  2. 有几个类实现了这个协议,每个类都适用于不同的iOS版本。
  3. 存在一个类,只有preps才能选择正确的版本。这个版本选择可以通过多种方式完成,我坚持使用#available
  4. 数据源协议:

    protocol ViewControllerDataSourcing: class {
        var text:String { get }
    }
    

    它的实现:

    class ViewControllerDataSourceIOS10: ViewControllerDataSourcing {
        var text: String {
            return "This is iOS 10"
        }
    }
    
    class ViewControllerDataSourceIOS11: ViewControllerDataSourcing {
        var text: String {
            return "This is iOS 11"
        }
    }
    
    class ViewControllerDataSourceIOSUnknown: ViewControllerDataSourcing {
        var text: String {
            return "This is iOS Unknown"
        }
    }
    

    选择正确版本类的类:

    class DataSourceSelector{
        class func dataSource() -> ViewControllerDataSourcing {
            if #available(iOS 11, *) {
                return ViewControllerDataSourceIOS11()
            }
            if #available(iOS 10, *) {
                return ViewControllerDataSourceIOS10()
            }
            return ViewControllerDataSourceIOSUnknown()
        }
    }
    

    最后是视图控制器

    class ViewController: UIViewController {
    
        var dataSource: ViewControllerDataSourcing?
    
        @IBOutlet weak var label: UILabel!
        override func viewDidLoad() {
            super.viewDidLoad()
            self.dataSource = DataSourceSelector.dataSource()
            label.text = dataSource?.text
        }
    }
    

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

    在现实世界的代码中,我可能不会在视图控制器中设置数据源,而是使用视图控制器结构或配置程序来设置它。

答案 2 :(得分:0)

&#34;一个班级的两个版本&#34;听起来像一个基类和两个子类。您可以通过询问例如在运行时基于系统版本来实例化所需的子类。 ProcessInfo。