美文网首页
Swift 的类和结构体(一些坑和解决办法)

Swift 的类和结构体(一些坑和解决办法)

作者: 非叼牛 | 来源:发表于2023-10-15 10:26 被阅读0次

写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
    }
}

本文章是实用性和个人理解的结合,如有规范上的问题或建议,欢迎提出!

相关文章

网友评论

      本文标题:Swift 的类和结构体(一些坑和解决办法)

      本文链接:https://www.haomeiwen.com/subject/halhvdtx.html