Swift Set转NSMutableSet遇异常:反向转换正常但正向转后nsSet2为nil
解决Swift Set转NSMutableSet出现nil的问题
我来帮你排查这个转换失败的问题~其实核心原因大多和Swift Set里的元素类型是否兼容Objective-C有关,NSMutableSet是Objective-C的集合类,只能存储Objective-C对象,要是Swift Set里的元素不符合这个要求,转换就会返回nil。
先看正确的转换示例
如果你的Swift Set里是Objective-C兼容的类型(比如String、Int会自动桥接成NSString、NSNumber),转换是完全没问题的:
let swiftStringSet: Set<String> = ["Apple", "Banana", "Cherry"] let nsMutableSet1 = NSMutableSet(set: swiftStringSet) // 这里nsMutableSet1是正常的NSMutableSet实例,不会是nil
为什么会出现nil?常见两种情况
- 元素是Swift专属类型(非Obj-C兼容)
比如Swift的结构体、没有标记@objc的枚举,或者自定义的非NSObject子类,这些类型无法被桥接成Objective-C对象,转换时NSMutableSet无法处理,就会返回nil:
// 例子:Swift结构体 struct Fruit { let name: String } let swiftStructSet: Set<Fruit> = [Fruit(name: "Apple")] let nsMutableSet2 = NSMutableSet(set: swiftStructSet) // 这里nsMutableSet2就是nil,因为Fruit是Swift结构体,不是Obj-C对象
- 元素包含Optional类型
NSMutableSet不能存储nil值,如果你的Swift Set里是Optional类型(比如Set<String?>),转换时遇到nil元素会直接导致转换失败,或者丢失元素,甚至返回nil:
let swiftOptionalSet: Set<String?> = ["Apple", nil, "Banana"] let nsMutableSet3 = NSMutableSet(set: swiftOptionalSet) // 这里nsMutableSet3大概率是nil,因为nil无法被NSMutableSet接收
解决办法
针对上面的情况,你可以这样调整:
- 使用Objective-C兼容的元素类型:优先用NSString、NSNumber、NSArray等原生Obj-C类型,或者让自定义类型继承自NSObject并标记@objc:
@objc class Fruit: NSObject { let name: String init(name: String) { self.name = name super.init() } } let swiftClassSet: Set<Fruit> = [Fruit(name: "Apple")] let nsMutableSet4 = NSMutableSet(set: swiftClassSet) // 这次转换成功,nsMutableSet4是有效的实例
- 移除Optional元素:如果你的Set里有Optional,先过滤掉nil值,再转换:
let swiftOptionalSet: Set<String?> = ["Apple", nil, "Banana"] // 先过滤nil,得到非Optional的Set let nonOptionalSet = swiftOptionalSet.compactMap { $0 } let nsMutableSet5 = NSMutableSet(array: nonOptionalSet) // 这里nsMutableSet5是正常的,包含"Apple"和"Banana"
如果还是有问题,可以先检查下你的Swift Set里的元素类型,确认每个元素都能被桥接成Objective-C对象,这样转换就不会返回nil啦~
内容的提问来源于stack exchange,提问作者Senseful
相关产品推荐
相关产品推荐

