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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
Haha_bj37 分钟前
Swift UI 状态管理
ios·app
2501_916007473 小时前
iOS 应用性能测试的工程化流程,构建从指标采集到问题归因的多工具协同测试体系
android·ios·小程序·https·uni-app·iphone·webview
源码_V_saaskw3 小时前
JAVA国际版同城跑腿源码快递代取帮买帮送同城服务源码支持Android+IOS+H5
android·java·ios·微信小程序
tbit4 小时前
fluwx 拉起小程序WXLog:Error:fail to load Keychain status:-25300, keyData null:1
flutter·ios·微信小程序
Sheffi5 小时前
iOS 内存管理深度解析:从原理到实践
ios
QuantumLeap丶6 小时前
《Flutter全栈开发实战指南:从零到高级》- 19 -手势识别
flutter·ios·前端框架
00后程序员张6 小时前
iOS 抓不到包怎么办?从 HTTPS 解密、QUIC 排查到 TCP 数据流分析的完整解决方案
android·tcp/ip·ios·小程序·https·uni-app·iphone
Haha_bj7 小时前
Swift UI数据存储
ios
Zender Han18 小时前
Flutter 新版 Google Sign-In 插件完整解析(含示例讲解)
android·flutter·ios·web
Digitally19 小时前
如何在iPhone上共享日历
ios·iphone