这里每天分享一个 iOS 的新知识,快来关注我吧
前言
上次的文章中,我们讲到了 mutating
这个关键字,当时提到的所有示例都是关于在方法中修改属性的,但 Swift 还提供了一种将某些上下文标记为非可变的方法。
这个关键字是 nonmutating
,用于标记值类型(枚举、结构体)中的方法。虽然实际的应用场景非常少,但在某些情况下它仍然是一个有用的功能。
nonmutating 的使用方法
nonmutating
关键字也是直接标记在方法名前面的,用来向编译器保证,在这个方法中并不会改变任何自身的属性:
swift
struct Point {
var x = 0.0, y = 0.0
nonmutating func description() -> String {
return "(\(x), \(y))"
}
}
nonmutating
关键字标记在 description
方法上,表明我们不会在 description
方法里对自身做出修改,不过......好像没什么用对吧?因为就算不加 nonmutating
关键字,程序一样会正常运行。
实际的应用场景
其实 nonmutating
关键字更多被用在计算属性(computed properties)的 set
方法上。
计算属性本质上是一种方法,可以通过 get
和 set
来访问和修改值。如果你想在 set
方法中改变其他属性而不改变该属性本身,你就可以使用 nonmutating set
。
举个例子,假如我们有一个存储工具类叫 Storage
,里面有个计算属性叫 userName
,当获取 userName
时,从 UserDefault
中获取(get
方法),当设置 userName
时,把新值存储到 UserDefault
中(set
方法)。
csharp
struct Storage {
private let userNameKey = "userNameKey"
var userName: String? {
get {
return UserDefaults.standard.string(forKey: userNameKey)
}
set {
UserDefaults.standard.set(newValue, forKey: userNameKey)
}
}
}
当我们用 let
创建一个 Storage
时,设置 userName
发现报错了:
这有点反直觉,因为在整个 userName
的 get
和 set
过程中,都没有修改其本身或者属性,但很明显编译器并不能进一步分析你的底层代码,而是简单粗暴的认为,只要有 set 方法,就以为你要做修改,因此报错。
想要修复这个报错,就需要用 nonmutating
关键字了,只需要在 set 方法前加上这个关键字,就可以正常运行了。
c
struct Storage {
...
nonmutating set {
UserDefaults.standard.set(newValue, forKey: userNameKey)
}
...
}
另外,在协议中也可以使用这个关键字:
swift
protocol Storage {
var userName: String? { get nonmutating set }
}
总结
通过这个关键字可以显式告诉编译器该方法/访问器不会改变其值,同时也为了代码的安全,编译器不会让你从 nonmutating
的方法中访问该类型的任何可变成员。
希望通过本文能让你深入了解 nonmutating
关键字的用法和作用,虽然在实际开发过程中大概用不上,但知道一下总是好的。
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!