在易出错的初始值设定项 swift 1.2 中分配 let 变量
Assigning let variable in fallible initializer swift 1.2
我有一个带有易错初始化器的结构,不是实例方法,而是初始化器。更新到 1.2 后,当我尝试在初始化程序中分配 let
属性 时,我收到以下错误 Cannot assign to 'aspectRatio' in self
。我的代码如下:
import Foundation
public struct MediaItem
{
public let url: NSURL!
public let aspectRatio: Double
public var description: String { return (url.absoluteString ?? "no url") + " (aspect ratio = \(aspectRatio))" }
// MARK: - Private Implementation
init?(data: NSDictionary?) {
var valid = false
if let urlString = data?.valueForKeyPath(TwitterKey.MediaURL) as? NSString {
if let url = NSURL(string: urlString as String) {
self.url = url
let h = data?.valueForKeyPath(TwitterKey.Height) as? NSNumber
let w = data?.valueForKeyPath(TwitterKey.Width) as? NSNumber
if h != nil && w != nil && h?.doubleValue != 0 {
aspectRatio = w!.doubleValue / h!.doubleValue
valid = true
}
}
}
if !valid {
return nil
}
}
struct TwitterKey {
static let MediaURL = "media_url_https"
static let Width = "sizes.small.w"
static let Height = "sizes.small.h"
}
}
我的问题是我该怎么做才能解决这个问题?
Swift 1.2 关闭了与 let
属性有关的漏洞:
The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized, not reassigned or mutated after initialization.
该规则正是您想要违反的。 aspectRatio
是一个 let
属性 并且你已经在它的声明中给了它一个值:
public let aspectRatio: Double = 0
所以在我们到达初始化器之前,aspectRatio
有它的初始值 — 0。这是它唯一可以拥有的值。新规则意味着你可以永远不会再次分配给aspectRatio
,甚至在初始化程序中也不行
解决方案是(这始终是正确的方法):在其声明中为其分配 no 值:
public let aspectRatio: Double
现在,在初始值设定项中,或者分配它 0 或者分配它 w!.doubleValue / h!.doubleValue
。换句话说,在初始化程序中处理 every 的可能性,once。那将是 唯一 一次,你可以这样或那样地分配 aspectRatio
一个值。
如果你仔细想想,你会发现这是一种更加明智和一致的方法;以前,您对 let
的含义有点含糊其词,而新规则正确地阻止了您这样做。
在您重写代码时,您未能在您打算退出的情况下初始化所有属性并且 return nil
。我知道这似乎违反直觉,但你不能那样做。您必须初始化所有属性 即使 您打算摆脱困境。这个我讨论的很清楚in my book:
A failable class initializer cannot say return nil
until after it has completed all of its own initialization duties. Thus, for example, a failable subclass designated initializer must see to it that all the subclass’s properties are initialized and must call super.init(...)
before it can say return nil
. (There is a certain delicious irony here: before it can tear the instance down, the initializer must finish building the instance up.)
编辑: 请注意,从 Swift 2.2 开始,此要求将被取消。 return nil
before 初始化属性是合法的。这将使 class 初始值设定项与结构初始值设定项相提并论,这已经是合法的。
我有一个带有易错初始化器的结构,不是实例方法,而是初始化器。更新到 1.2 后,当我尝试在初始化程序中分配 let
属性 时,我收到以下错误 Cannot assign to 'aspectRatio' in self
。我的代码如下:
import Foundation
public struct MediaItem
{
public let url: NSURL!
public let aspectRatio: Double
public var description: String { return (url.absoluteString ?? "no url") + " (aspect ratio = \(aspectRatio))" }
// MARK: - Private Implementation
init?(data: NSDictionary?) {
var valid = false
if let urlString = data?.valueForKeyPath(TwitterKey.MediaURL) as? NSString {
if let url = NSURL(string: urlString as String) {
self.url = url
let h = data?.valueForKeyPath(TwitterKey.Height) as? NSNumber
let w = data?.valueForKeyPath(TwitterKey.Width) as? NSNumber
if h != nil && w != nil && h?.doubleValue != 0 {
aspectRatio = w!.doubleValue / h!.doubleValue
valid = true
}
}
}
if !valid {
return nil
}
}
struct TwitterKey {
static let MediaURL = "media_url_https"
static let Width = "sizes.small.w"
static let Height = "sizes.small.h"
}
}
我的问题是我该怎么做才能解决这个问题?
Swift 1.2 关闭了与 let
属性有关的漏洞:
The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized, not reassigned or mutated after initialization.
该规则正是您想要违反的。 aspectRatio
是一个 let
属性 并且你已经在它的声明中给了它一个值:
public let aspectRatio: Double = 0
所以在我们到达初始化器之前,aspectRatio
有它的初始值 — 0。这是它唯一可以拥有的值。新规则意味着你可以永远不会再次分配给aspectRatio
,甚至在初始化程序中也不行
解决方案是(这始终是正确的方法):在其声明中为其分配 no 值:
public let aspectRatio: Double
现在,在初始值设定项中,或者分配它 0 或者分配它 w!.doubleValue / h!.doubleValue
。换句话说,在初始化程序中处理 every 的可能性,once。那将是 唯一 一次,你可以这样或那样地分配 aspectRatio
一个值。
如果你仔细想想,你会发现这是一种更加明智和一致的方法;以前,您对 let
的含义有点含糊其词,而新规则正确地阻止了您这样做。
在您重写代码时,您未能在您打算退出的情况下初始化所有属性并且 return nil
。我知道这似乎违反直觉,但你不能那样做。您必须初始化所有属性 即使 您打算摆脱困境。这个我讨论的很清楚in my book:
A failable class initializer cannot say
return nil
until after it has completed all of its own initialization duties. Thus, for example, a failable subclass designated initializer must see to it that all the subclass’s properties are initialized and must callsuper.init(...)
before it can sayreturn nil
. (There is a certain delicious irony here: before it can tear the instance down, the initializer must finish building the instance up.)
编辑: 请注意,从 Swift 2.2 开始,此要求将被取消。 return nil
before 初始化属性是合法的。这将使 class 初始值设定项与结构初始值设定项相提并论,这已经是合法的。