iOS:Non-mutating 关键字介绍

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

上次的文章中,我们讲到了 mutating 这个关键字,当时提到的所有示例都是关于在方法中修改属性的,但 Swift 还提供了一种将某些上下文标记为非可变的方法。

mutating 的使用和实现原理

这个关键字是 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 方法上。

计算属性本质上是一种方法,可以通过 getset 来访问和修改值。如果你想在 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 发现报错了:

这有点反直觉,因为在整个 userNamegetset 过程中,都没有修改其本身或者属性,但很明显编译器并不能进一步分析你的底层代码,而是简单粗暴的认为,只要有 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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
小江村儿的文杰13 小时前
UE4 iOS Package的过程与XCode工程中没有游戏Content的原因
macos·ios·ue4·xcode
__WanG17 小时前
Flutter将应用打包发布到App Store
前端·flutter·ios
安和昂20 小时前
【iOS】bug调试技巧
ios·bug·cocoa
emperinter20 小时前
WordCloudStudio Now Supports AliPay for Subscriptions !
人工智能·macos·ios·信息可视化·中文分词
AirDroid_cn21 小时前
iPhone或iPad接收的文件怎么找?怎样删除?
ios·iphone·ipad·文件传输
Swift社区1 天前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
#摩斯先生1 天前
Swift从0开始学习 对象和类 day3
ios·xcode·swift
没头脑的ht1 天前
Swift内存访问冲突
开发语言·ios·swift
#摩斯先生1 天前
Swift从0开始学习 并发性 day4
ios·xcode·swift
_黎明1 天前
【Swift】类型标注、类型安全和类型推断
swift