Swift5中如何修改嵌套结构体数组内的键值?含可选键场景
Swift5 嵌套结构体数组的键值修改方案及可选类型处理
一、更优的嵌套结构体数组修改方案
Swift 中结构体是值类型,数组内的元素为值拷贝,直接修改嵌套数组内的结构体属性需要先取出元素、修改后再放回数组,步骤繁琐。我们可以通过自定义 Array 扩展简化这个流程:
通用 Array 扩展实现便捷修改
extension Array { mutating func modifyElement(at index: Index, _ transform: (inout Element) throws -> Void) rethrows { guard indices.contains(index) else { return } var element = self[index] try transform(&element) self[index] = element } }
这个扩展允许通过闭包直接修改指定下标的数组元素,嵌套场景下可链式调用,代码更简洁:
struct Article { var id: Int var book: [Book] } struct Book { var page: Int var author: [Author] } struct Author { var visited: Bool } // 使用示例 var a = Article(id: 1, book: [Book(page: 11, author: [Author(visited: true)])]) print(a) // 链式修改嵌套数组中的 visited 属性 a.book.modifyElement(at: 0) { $0.author.modifyElement(at: 0) { $0.visited = false } } print(a)
二、可选类型的处理场景
1. 结构体属性为可选类型
如果结构体的属性本身是可选类型(比如 Author 的 visited 是 Bool?),修改逻辑和非可选类型几乎一致,支持赋值为具体值或 nil:
struct Author { var visited: Bool? // 可选属性 } var a = Article(id: 1, book: [Book(page: 11, author: [Author(visited: true)])]) // 修改为具体值 a.book.modifyElement(at: 0) { $0.author.modifyElement(at: 0) { $0.visited = false } } // 设置为 nil a.book.modifyElement(at: 0) { $0.author.modifyElement(at: 0) { $0.visited = nil } }
2. 嵌套数组为可选类型
如果嵌套的数组本身是可选类型(比如 Article 的 book 是 [Book]?),可以给 Optional<Array> 添加扩展,自动处理解包和下标边界判断,避免手动写大量 if let:
struct Article { var id: Int var book: [Book]? // 可选数组 } struct Book { var page: Int var author: [Author]? // 可选数组 } // 可选数组的扩展 extension Optional where Wrapped: MutableCollection, Wrapped.Index == Int { mutating func modifyElement(at index: Wrapped.Index, _ transform: (inout Wrapped.Element) throws -> Void) rethrows { guard var array = self, array.indices.contains(index) else { return } try array.modifyElement(at: index, transform) self = array } } // 使用示例 var a = Article(id: 1, book: [Book(page: 11, author: [Author(visited: true)])]) // 直接链式修改,无需手动解包 a.book.modifyElement(at: 0) { $0.author.modifyElement(at: 0) { $0.visited = false } } // 数组为 nil 时,调用不会崩溃,无任何操作 var b = Article(id: 2, book: nil) b.book.modifyElement(at: 0) { $0.author.modifyElement(at: 0) { $0.visited = false } }
内容的提问来源于stack exchange,提问作者jacobcan118
相关产品推荐
相关产品推荐

