Swift中为可选Set定义insert函数遇异常:扩展无效但独立函数正常
问题描述
我想给初始为nil的可选Set插入新元素,写了个Optional扩展实现myInsert方法,但调用后没法成功插入元素;把同样逻辑写成独立函数却能正常运行,我觉得是Xcode的问题,求解答。
扩展代码
extension Optional where Wrapped == Set<String> { func myInsert(_ value: String) -> Self { if let unwrappedSet: Set<String> = self { var newSet: Set<String> = unwrappedSet newSet.insert(value) return newSet } else { let set: Set<String>? = [value] return set } } }
扩展调用示例
func myTest() -> Set<String>? { var set: Set<String>? = nil set.myInsert("Hello") return set } if let set: Set<String> = myTest() { print(set) }
独立函数代码
func myInsert(set: Set<String>?, value: String) -> Set<String>? { if let unwrappedSet: Set<String> = set { var newSet: Set<String> = unwrappedSet newSet.insert(value) return newSet } else { let set: Set<String>? = [value] return set } }
独立函数调用示例及结果
let set: Set<String>? = nil let newSet = myInsert(set: set, value: "Hello") let newSet2 = myInsert(set: newSet, value: "World") print(newSet2)
Optional(Set(["Hello", "World"]))
问题解答
根本不是Xcode的问题,问题出在你的扩展方法调用逻辑和方法设计上:
1. 核心原因
Swift里的Set和Optional都是值类型,值类型的实例方法默认不会修改自身。你的原扩展方法myInsert只是基于当前可选Set的值创建了一个新的Set并返回,但你在调用时没有将返回值赋值给原变量set,所以原变量始终保持nil状态。
而独立函数的调用方式是将返回值赋值给新变量,因此能正确获取到插入元素后的Set。
2. 两种解决方式
方式一:调用时接收返回值,更新原变量
修改你的调用代码,将扩展方法的返回值赋值回原变量:
func myTest() -> Set<String>? { var set: Set<String>? = nil set = set.myInsert("Hello") // 关键:将返回值赋值给原变量 return set }
这样调用后,set就会被更新为包含"Hello"的可选Set。
方式二:将扩展改为mutating方法,实现原地修改
如果希望像普通Set的insert方法一样原地修改,可以把扩展方法标记为mutating,直接修改self的值:
extension Optional where Wrapped == Set<String> { mutating func myInsert(_ value: String) { if var unwrappedSet = self { unwrappedSet.insert(value) self = unwrappedSet } else { self = [value] } } }
此时原调用代码无需修改,set.myInsert("Hello")会直接修改原变量,无需手动赋值。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

