【问题标题】:How to implement a failable initializer for a class conforming to NSCoding protocol in Swift?如何在 Swift 中为符合 NSCoding 协议的类实现可失败的初始化程序?
【发布时间】:2015-11-23 20:44:54
【问题描述】:

如何为符合 NSCoding 协议的类实现可失败的初始化程序?

我收到以下错误:
1. 行override init() {}:属性“self.videoURL”未在隐式生成的 super.init 调用中初始化
2.return nil行:类实例的所有存储属性必须在从初始化器返回nil之前初始化

我已经看到 Best practice to implement a failable initializerAll stored properties of a class instance must be initialized before returning nil 对我有很大帮助,但是由于我的类也符合 NSCoding 协议,所以我不知道如何在我的情况下实现可失败的初始化程序。

关于如何实现可失败初始化器的任何建议?

class CustomMedia : NSObject, NSCoding {
  var videoTitle: String?
  let videoURL: NSURL!

  override init() {}

  init?(title: String?, urlString: String) {
    // super.init()
    if let url = NSURL(string: urlString) {
       self.videoURL = url
       self.videoTitle = title
    } else {
       return nil
    }
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.videoTitle, forKey: PropertyKey.videoTitle)
    aCoder.encodeObject(self.videoURL, forKey: PropertyKey.videoURL)
  }

  required init(coder aDecoder: NSCoder) {
    videoTitle = aDecoder.decodeObjectForKey(PropertyKey.videoTitle) as? String
    videoURL = aDecoder.decodeObjectForKey(PropertyKey.videoURL) as! NSURL
  }
}

【问题讨论】:

  • 你为什么要做override init() {}
  • @DanVanWinkle 我已经看到它在其他示例中以这种方式实现以符合 NSCoding 并且它没有导致任何错误。太好了,我已将其注释掉,第一个错误消失了。

标签: swift


【解决方案1】:

更新:这已在 Swift 2.2 更新中得到解决,您不再需要在初始化程序失败之前分配 nil 值并调用 super。

对于 2.2 之前的 Swift 版本:

不幸的是,您实际上必须在返回 nil 之前初始化您的值。

这是有效的解决方案:

class CustomMedia : NSObject, NSCoding {
   var videoTitle: String?
   var videoURL: NSURL!

   init?(title: String?, urlString: String) {
      super.init()

      if let url = NSURL(string: urlString) {
         self.videoURL = url
         self.videoTitle = title
      } else {
         self.videoURL = nil
         self.videoTitle = nil
         return nil
      }
   }

   func encodeWithCoder(aCoder: NSCoder) {
      aCoder.encodeObject(self.videoTitle, forKey: PropertyKey.videoTitle)
      aCoder.encodeObject(self.videoURL, forKey: PropertyKey.videoURL)
   }

   required init(coder aDecoder: NSCoder) {
      videoTitle = aDecoder.decodeObjectForKey(PropertyKey.videoTitle) as? String
      videoURL = aDecoder.decodeObjectForKey(PropertyKey.videoURL) as! NSURL
   }
}

【讨论】:

  • 我该怎么做?我在返回零之前输入了videoURL = NSURL(string: "https://www.google.com/")!,但它没有用。 Sitll 得到错误:必须在从初始化程序返回 nil 之前初始化类实例的所有存储属性。
  • 我必须在返回 nil 之前输入上面的代码,而且我还必须清理项目。否则我收到上述错误。无法弄清楚,因为我没有在每次构建之前清理项目。
  • @Andrej 您可以只分配 nil,因为类型是可选的,您不必创建有效的 URL。
  • 不,videoURL 不是可选的,所以我不能将它设置为 nil。只有 videoTitle 是可选的,它不需要在返回 nil 之前进行初始化。可能你没注意“!”在var videoURL: NSURL!
  • NSURL! 是一个可选类型,它是一个隐式展开的可选。当它是nil 时,您无法在不导致崩溃的情况下引用它。不过,您绝对可以指定nil
猜你喜欢
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多