【问题标题】:Variable (enum?) holding one of two types in Swift 2变量(枚举?)持有 Swift 2 中的两种类型之一
【发布时间】:2015-10-12 08:24:24
【问题描述】:

UIViewController 子类中需要声明一个名为webView 的变量,其类型可以是UIWebViewWKWebView(取决于iOS 版本)。

有没有比以下选项之一更好的方法(也许使用枚举?):

  1. 声明UIView类型的变量,然后每次我需要访问它时有条件地转换为这两种类型
  2. 不是在公共父类UIViewController超类中声明变量,而是在两个特定UIViewController子类中两次声明特定类型的变量?感觉它违反了“不要重复自己”/DRY 原则。

【问题讨论】:

  • 我目前无法测试,但是#if os (watchOS) typealias MyWebView = WKWebView #else typealias MyWebView = UIWebView #endif(“构建配置语句”)呢?
  • 我喜欢这种方法,但不幸的是我需要一个 runtime 解决方案,而#if`` & typealias` 似乎是编译时功能,因此在运行时不可用。除非我误解了什么?
  • 是的,这是在编译时评估的。其实我昨天在电话里看到你的问题时误解了这个问题。我以为你想在 iOS 和 watchOS 应用程序之间共享代码,这对我来说很愚蠢。
  • 您可以做的是定义一个 protocol 包含您要在视图上调用的所需方法,然后使 UIWebView 和 WKWebView 都符合该协议(通过类别) 并将实例变量声明为id<MyWebViewProtocol>
  • @MartinR - 谢谢 - 如果您将此作为答案转发,我会将其标记为已接受。

标签: swift enums


【解决方案1】:

您可以定义一个协议,其中包含您要在视图上调用的常用方法:

protocol MyWebView {
    // ...
}

然后使UIWebViewWKWebView 都符合该协议 (通过扩展):

extension UIWebView : MyWebView {

}

@available(iOS 8.0, *)
extension WKWebView : MyWebView {

}

现在您可以将实例变量声明为

var webView : MyWebView!

并根据iOS版本进行初始化:

if #available(iOS 8, *){
    webView = WKWebView()
} else {
    webView = UIWebView()
}

【讨论】:

  • 这种方法似乎有问题。如果部署目标是 iOS 7,则链接器失败。我可能不得不删除答案...
  • 你只需要弱链接WebKit框架来解决这个问题:)
【解决方案2】:

我在我的一个应用程序中遇到了类似的问题,使用的是不同的已弃用框架。这个解决方案对我有用:

如下图创建一个属性:

var webView: AnyObject!

viewDidLoad 中,使用以下代码初始化 Web 视图:

if #available(iOS 9, *){
    webView = WKWebView()
} else {
    webView = UIWebView()
}

在您的代码的其他地方,当您需要使用此 Web 视图执行某些操作时,您需要执行类似的操作:

if #available(iOS 9, *){
    let newWebView = webView as! WKWebView
    // use newWebView
} else {
    let oldWebView = webView as! UIWebView
    // use oldWebView
}

注意:Martin R 的使用类型别名的建议可能也有效,但我已经测试过这个解决方案。

【讨论】:

  • 谢谢 - 这实际上是我在原始帖子中提出的选项 1.。绝对仍然愿意接受其他建议。
猜你喜欢
  • 1970-01-01
  • 2022-07-25
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
相关资源
最近更新 更多