2017-09-07 28 views
2

iOS 11最近添加了一個我想使用的新功能,但我仍然需要支持舊版本的iOS。有兩種方法可以編寫同一個類兩次,並且讓iOS的新版本使用一個版本的類,而舊版iOS使用另一個版本?根據iOS版本使用不同的類實現?

(注:本來我用if #available(iOS 11, *)但我在,我認爲這純粹是清潔的,如果可能有2個版本的類這麼多的地方使用它也許有使用@availble莫名其妙的一種方式?我專注於使用@available而不是預編譯器#IFDEF的東西,因爲它好像「可用」標籤是現在在Swift中使用它的首選方式?)

+1

這將有助於如果您在您的問題,一些相關的代碼。舉例說明你在做什麼,並清楚描述你想做什麼。 – rmaddy

+0

我認爲真正的問題是'#available'沒有交流。例如,如果這是iOS 11,則可以包括這些東西,但如果這是iOS 11,則不能排除這些東西。 – matt

+0

您的類的兩個版本是否具有完全相同的成員? – Sweeper

回答

0

「兩個版本的類」聽起來像一個基類和兩個子類。你可以通過詢問例如在運行時基於系統版本實例化期望的子類。 ProcessInfo。

2
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)得到您的實例,並用這個你忘了在代碼的其餘部分的檢查,如果有可能使用新的功能。

只有爲兩個類建立相同的接口(即使它是該方法的虛擬版本),該解決方案也是可能的。

0

高質量的代碼遵循幾個原則。一個是單責任原則,即指出一個班級應該只有一個責任,或者 - 正如Bob叔叔所說 - 應該只有一個班級改變的原因。
另一個原則是依賴倒置原則:一個類不應該依賴較低級別的類,而應該依賴這些較低級別類實現的抽象(協議)。這也意味着所有依賴必須傳遞給使用它們的類。

施加在你的問題的一個解決方案可以是:

  1. 視圖控制器具有被定義爲一個協議數據源屬性。
  2. 幾個類實現了這個協議,每個都適用於不同的iOS版本。
  3. 存在一個只有準備選擇正確版本的類。這個版本的選擇可以以多種方式來完成,我堅持#available

數據源協議:

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 
    } 
} 

這是一個非常簡單的例子,應突出負責不同的組件。

在現實世界的代碼中,我可能不會在視圖控制器中設置數據源,但使用視圖控制器結構或配置器來設置它。

0

我遇到了同樣的問題。我最終加入上面我只是想在iOS中的一個特定版本,支持方法@available解決這個問題:

@available(iOS 11.3, *) 
func myMethod() { .. } 
相關問題