ios - 没有初始化器但有属性观察器的 Swift 类

标签 ios swift struct

我刚开始学习 swift,对类初始化器有疑问。这是我的示例代码:

struct Resolution {
  var width = 0
  var height = 0
}

let someResolution = Resolution()

class TV {
  var res: Resolution! {
    didSet {
      res.width = 1
      res.height = 1
    }
  }
}

var television = TV()
var resolution = Resolution()
television.res = resolution

我正在尝试使用属性观察器。当我隐式解包 struct 属性观察者类型时,一切正常。否则,它会说“类没有初始化器。我很困惑为什么我应该隐式解包结构。提前致谢!

最佳答案

从你的问题来看还不是很清楚,但我想你是在问为什么你不能替换这个:

var res: Resolution! {

...有了这个:

var res: Resolution {

您的线索来自完整的编译器错误消息,您可以通过查看编译器日志(如果您在 playground 中,则可以查看 playground 控制台):

error: class 'TV' has no initializers
class TV {
      ^
note: stored property 'res' without initial value prevents synthesized initializers
  var res: Resolution {
      ^
error: 'TV' cannot be constructed because it has no accessible initializers
var television = TV()

当属性的类型是 Resolution! 时,您是在说,“它可以为 nil,但如果有人试图在它为 nil 时阅读它,那么那是一场可怕的灾难,我的整个应用程序都应该崩溃。”所以 Swift 初始化 TV 并将 res 设置为 nil,并希望您立即将其设置为其他值。

但是,当属性的类型为 Resolution 时,您是在说,“它永远不可能为零,永远不会,即使没有人在看。”这意味着 res 必须TV 被实例化的那一刻起就有一个值。但是这个值应该是多少呢?没有默认设置。如果类型是 Resolution,您有两个选择:

  1. 使用属性初始值设定项将其设置为某个默认值(这看起来就像您正在尝试做的那样):

     class TV {
       var res: Resolution = Resolution(width: 1, height: 1)
     }
    

    ...或者使用初始化器,你可以让 Swift 推断类型:

     class TV {
       var res = Resolution(width: 1, height: 1)
     }
    
  2. 请创建 TV 的人在实例化类时指定初始值:

    class TV {
      init(res: Resolution) {
        self.res = res
      }
    
      var res: Resolution {
        didSet {
          res.width = 1
          res.height = 1
        }
      }
    }
    
    var resolution = Resolution()
    var television = TV(res: resolution)
    

旁白:所有这些完全没有意义,因为您在设置分辨率后立即将宽度和高度更改为 1(什么?!),但它确实可以编译。

那么来自编译器的“合成初始值设定项”消息? Swift 会自动为你的类创建一个什么都不做的空 init() ,但如果有任何非可选属性要初始化则不会。如果有,则必须编写自己的初始化程序。

(请注意,如果 TV 是一个结构,那么 Swift 为您生成那个 init(res:)。它处理结构,但不是类。)

第三种选择是制作 Resolution? 类型:

class TV {
  var res: Resolution? {
    didSet {
      res?.width = 1
      res?.height = 1
    }
  }
}

这是一个比 Resolution! 更好的选择,后者只是等待发生的崩溃。隐式解包选项应该只是最后的手段,在非常具体、经过仔细考虑的情况下使用。

关于ios - 没有初始化器但有属性观察器的 Swift 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33558409/

相关文章:

python - 如何使用 Python 响应 HTTP 请求

C语言: memory allocation of a structure of two char* pointers

arrays - 在 Swift 中将位数组转换为结构数组

c - 为什么 char 数组需要 strcpy 而 char star 不需要 - 在 C 中使用结构

swift - 我的 webView 占用了太多内存吗?

ios - 无法将调试器附加到 UNNotificationServiceExtension

ios - AVPlayer 从 iOS 7 后台通知播放音频

ios - 如何在 iOS Swift 2.0 中更改导航项标题的背景色和前景色?

swift - 错误: Cannot find an overload for 'contains' that accepts an argument type in while loop

json - 使用 Swift 脚本打印有效的 JSON