写swift也有一段时间了,踩了一些坑,总结一下
1.发现坑
当你选择了一些model传给下一个VC,在下一个VC改变了model后,再返回到上一个VC时,会发现model也跟着变了。
例:
class HomeViewController: UIViewController {
func gotoTaskVC() {
var editArray : [FileModel] = []
for model in dataArray {
if model.isSelect {
editArray.append(model)
}
}
navigationController?.pushViewController(ACTaskViewController(taskArray: editArray, format: formatStr), animated: true)
}
class TaskViewController: UIViewController {
public init(taskArray: [FileModel]) {
for model in taskArray {
model.isEdit = false
model.isSelect = false
}
self.taskArray = taskArray
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
因为OC写多了的原因,所以一直是以为是dataArray在某个地方被改变了。
因为实在找不出dataArray被改变了,所以开始想是不是swift的问题,后来找到
class是引用类型,struct是值类型
值类型在传递和赋值时将进行复制,而引用类型则只会使用引用对象的一个指向。
引用类型是在堆上,而值类型是在栈上进行存储和操作。相比栈上的操作,对上的操作更加复杂耗时,所以苹果官方推荐使用结构体,这样可以提高App运行的效率。
class有这几个功能struct没有的:
class可以继承,这样子类可以使用父类的特性和方法。
类型转换可以在runtime的时候检查和解释一个实例的类型。
可以用deinit来释放资源。
一个类可以被多次引用。
struct也有这样几个优势:
结构较小,适用于复制操作,相比于一个class的实例被多次引用更加安全。
无序担心内存泄漏或者多线程冲突问题。
2.解决
看了一下 FileModel 确实是 class
为了两个VC的model不互相影响,给 FileModel 加 NSCopying 和 NSMutableCopying 协议
class FileModel: NSObject, NSCopying, NSMutableCopying {
var name: String
var isEdit: Bool
var isSelect: Bool
init(name: String, isEdit: Bool, isSelect: Bool) {
self.name = name
self.isEdit = isEdit
self.isSelect = isSelect
}
func copy(with zone: NSZone? = nil) -> Any {
let model = ACFileModel(name: self.name, isEdit: self.isEdit, isSelect: self.isSelect)
return model
}
func mutableCopy(with zone: NSZone? = nil) -> Any {
let model = ACFileModel(name: self.name, isEdit: self.isEdit, isSelect: self.isSelect)
return model
}
}
3.优化
struct毕竟比class性能高,而且这个model的属性又不复杂,所以想着可以把它转为struct类型
注:
结构体是值类型,不可以继承
结构体内部的属性如果想要修改,要在内部的修改方法前加 mutating
转换后:
struct FileModel {
var name: String
var isEdit: Bool
var isSelect: Bool
mutating func changeName(name: String) {
name = name;
}
mutating func changeIsEdit(isEdit: Bool) {
isEdit = isEdit;
}
mutating func changeIsSelect(isSelect: Bool) {
isSelect = isSelect;
}
init(name: String, isEdit: Bool, isSelect: Bool) {
self.name = name
self.isEdit = isEdit
self.isSelect = isSelect
}
}