Swift 3中向结构体数组追加结构体时的可变操作错误问题
问题:如何对需要类型转换的值执行可变操作?
先来看你的代码背景:
你定义了这个结构体:
struct Note{ var date: String; var comment: String; }
然后创建了用于Table View分区的嵌套数组:
var data = [[Note()],[Contributors()]]
你尝试用这两段代码向Note数组追加实例时都报错:
data[0].append(Note(date: "06-06-2012",comment:"Created Note"))
(data[0] as! Note).append(Note(date: "06-06-2012",comment:"Created Note"))
错误提示:
Cannot use mutating member on immutable value of type 'Note'
问题根源
这里的核心问题是类型推断和类型转换错误:
- Swift会自动把
data的类型推断为[[Any]]——因为你同时放入了[Note]和[Contributors]两种不同类型的数组,编译器只能将它们统一为Any类型的元素。直接调用data[0].append时,data[0]被识别为Any,编译器不知道它是可变数组,因此不允许调用append。 - 你第二次尝试的
as! Note完全搞错了类型:data[0]是一个数组,不是单个Note实例。强制转换成Note不仅会运行时崩溃,而且Note结构体本身也没有append方法,这就是报错的直接原因。
正确的解决方法
方法1:安全类型转换后修改数组
你需要先将data[0]转换成[Note]类型,修改完成后再赋值回原数组:
// 先明确data的类型(避免编译器自动推断的模糊性) var data: [[Any]] = [[Note()], [Contributors()]] // 安全转换并追加元素 if var noteArray = data[0] as? [Note] { noteArray.append(Note(date: "06-06-2012", comment:"Created Note")) data[0] = noteArray }
如果你100%确定data[0]的类型就是[Note](不会出现类型不匹配),也可以用强制转换(但不推荐在不确定场景使用,容易崩溃):
var noteArray = data[0] as! [Note] noteArray.append(Note(date: "06-06-2012", comment:"Created Note")) data[0] = noteArray
方法2:用枚举实现类型安全(更推荐)
使用Any类型会带来类型不安全的隐患,更符合Swift设计理念的方式是用枚举区分不同分区的数据:
// 假设你的Contributors结构体定义如下 struct Contributors { /* 你的结构体内容 */ } struct Note{ var date: String; var comment: String; } // 定义枚举统一分区数据类型 enum TableSectionData { case notes([Note]) case contributors([Contributors]) } // 初始化分区数据 var data: [TableSectionData] = [.notes([Note()]), .contributors([Contributors()])] // 向notes分区追加元素 switch data[0] { case .notes(var notes): notes.append(Note(date: "06-06-2012", comment:"Created Note")) data[0] = .notes(notes) default: // 处理第一个分区不是notes的情况(比如打印错误日志) break }
这种方式让数据类型更清晰,完全避免了类型转换带来的崩溃风险,代码可读性也更高。
内容的提问来源于stack exchange,提问作者ThomasMcDonald
相关产品推荐
相关产品推荐

