Swift变量声明含义

时间:2014-12-16 21:48:27

标签: swift memory-management

这两个声明的区别是什么?哪一个更好?为什么呢?

... error = some NSError ...

1

var newUserInfo: [NSObject: NSObject] = [:]

if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
  newUserInfo = tempUserInfo
}

2

var newUserInfo: [NSObject: NSObject]

if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
  newUserInfo = tempUserInfo
} else {
  newUserInfo = [:]
}

3 个答案:

答案 0 :(得分:7)

从Swift 1.2开始,您现在可以将let与延迟分配一起使用,以便您可以使用if / else版本:

let newUserInfo: [NSObject: NSObject]

if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
  newUserInfo = tempUserInfo
} else {
  newUserInfo = [:]
}

但是,选项1将工作,因为有一条路径可能无法设置newUserInfo

(注意,从1.2b1开始,这不适用于全局变量,只适用于成员和局部变量,以防你在游乐场试试)

或者,您可以使用nil-coalescing运算符一次完成,如下所示:

let newUserInfo = (error.userInfo as? [NSObject:NSObject]) ?? [:]

编辑:Swift 1.2添加了let的延迟分配,使选项2现在与let一起使用,但也改变了as? vs ??的优先级,要求括号。

1.2之前的答案,以防您需要迁移类似的代码:

如果你问我,它们都没有特别吸引人。在这两种情况下,您都必须使用newUserInfo声明var,因为您没有一次性声明并分配它。

我建议:

let newUserInfo = error.userInfo as? [NSObject:NSObject] ?? [:]

答案 1 :(得分:2)

  • 在1. newUserInfo中,如果执行if分支,则分配两次。 2.在性能方面更好
  • 1.在newUserInfo初始化为空数组时,可以清楚地看到它。 2.使代码的可读性降低,因为您必须浏览代码才能知道它是否具有默认值
  • 如果可以在多个地方设置newUserInfo(例如,如果可以在多个if语句中对其进行初始化),则应在2.中复制else分支,这样1看起来更好

所以:在解决方案中没有。 1代码更易读,但解决方案没有。 2稍微高一点。

除了使用@AirspeedVelocity解决方案(比你的更好,没有冒犯:)),我更喜欢使用可选的,将newUserInfo设置为nil以表示没有价值 - 毕竟,那个选项是什么,不是吗?但当然这取决于您的具体需求。

答案 2 :(得分:0)

我首选的模式是:

struct TryUnrap<T> {
    typealias Tryee = () -> T?
    typealias Catchee = () -> T

    private var tryee: Tryee

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func catch(catchee: Catchee) -> T {
        if let result = tryee() {
            return result
        }
        return catchee()
    }
}

let error: NSError? = NSError()
let newUserInfo = TryUnrap {
    error?.userInfo as? [NSObject : NSObject]
}.catch {
    [:]
}
println("newUserInfo = \(newUserInfo)")

我更喜欢上述内容,因为我发现它对我来说更好。另请参阅Error-Handling in Swift-Language的答案4,了解使用相同模式的一般错误处理。