过滤器操作符在这种情况下不是最好的,它对你们中的一些人有用,因为类是通过引用传递的。
说明:(如果你想验证,可以复制下面的代码在一个playground中)。
class Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook.filter{ $0.id == 1 }.first?.title = "modified"
arrayBook.forEach { book in
print(book.title)
}
数组是按值而不是引用复制的,因此当您使用过滤器时,您正在创建一个新数组(与初始数组不同),但是当您修改新数组时,初始数组也会被修改,因为两者都指向相同的类(分类通过引用传递),因此在过滤器之后,您的数组将发生变化,新的数组将被释放。所以在这种情况下,它将打印“default”、“default”,然后是 “default, “modified”。
如果您将class 更改为struct 会发生什么情况,该值将通过值而不是引用传递,因此您将在内存中拥有两个具有不同值的数组,因此如果您再次通过arrayBooks,它将在之前打印过滤器"default","default",然后再次"default", "default"。因为当您使用过滤器时,您正在创建和修改一个新数组,如果您不存储它将被释放)。
解决方案是使用 map,创建一个包含所有值但包含我们想要的修改项或字段的新数组,然后用新数组替换我们的数组。这将在地图之前打印 "default", "default",然后是 "default", "modified"
这将适用于结构、类和你想要的一切:)。
struct Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook = arrayBook.map{
var mutableBook = $0
if $0.id == 1 {
mutableBook.title = "modified"
}
return mutableBook
}
arrayBook.forEach { book in
print(book.title)
}