我有两个控制器。第一个控制器从服务器加载列表并创建自定义对象列表WordList
。
class WordList {
let name: String
let releaseDate: Date
var words: [String]
let multiplier: Int
...
}
在第一个屏幕上,用户可以选择继续操作之前的列表。在下一个控制器上,从随机列表中选择一个随机词。出现单词后,在用户与之交互时将其删除。一旦用户不进行交互,就选择一个新单词,直到没有更多单词为止。如果我回到主控制器并选择我刚才使用过的相同列表,则该列表将为空。这就是我发送所选项目的方式。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? WordController {
var wordLists = [WordList]()
for index in tableView.indexPathsForSelectedRows! {
wordLists.append(lists[index.row]) // lists is a class property that is a WordList array.
}
// This was my first attempt. Values were copied but removed from this controller.
// for wordList in wordLists {
// destination.wordLists.append(wordList)
// }
// destination.wordLists = wordLists
// This was my second attempt. Values were also copied but removed from this controller.
destination.wordLists.append(contentsOf: wordLists)
}
}
我知道我必须传递列表的引用,而不是实际复制它,但是我不认为如果我通过从第一个数组中复制值来填充第二个数组,那将是如何工作的。
除了每次用户返回屏幕时都重新加载第一个控制器外,我该如何进行这项工作,以便用户可以重用已清除的列表?
答案 0 :(得分:4)
您说:
我知道我必须传递列表的引用,而不是实际复制它...
不,您要传递一个新数组。
...但是我不认为如果我通过复制第一个数组中的值来填充第二个数组,那将不会如此。
不幸的是,您不是从第一个数组“复制值”,而是从第一个数组复制WordList
引用到第二个数组。归根结底,问题不在于值类型的Array
,而是引用类型的WordList
。
WordList
是引用类型,因为它是class
。因此,当您从一个数组引用WordList
并将其添加到另一个数组时,第二个数组仍将引用相同的WordList
实例。
如果您不希望对其他阵列实例的操作影响原始实例,则可以:
将WordList
从引用类型(class
)更改为值类型(struct
):
struct WordList {
let name: String
let releaseDate: Date
var words: [String]
let multiplier: Int
}
如果确实需要使用class
,请编写自己的copy
方法以返回新实例。例如,您可能符合NSCopying
并编写了copy(with:)
:
extension WordList: NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
return WordList(name: name, releaseDate: releaseDate, words: words, multiplier: multiplier)
}
}
,然后在构建新数组时,附加副本而不是引用原始实例:
for index in tableView.indexPathsForSelectedRows! {
wordLists.append(lists[index.row].copy() as! WordList)
}
如果您不喜欢NSCopying
为Any
引入笨拙的copy
返回类型的事实,那么您也可以只定义copy
方法甚至编写自己的Copying
协议,例如:
protocol Copying {
associatedtype ObjectType = Self
func copy() -> ObjectType
}
extension WordList: Copying {
func copy() -> WordList {
return WordList(name: name, releaseDate: releaseDate, words: words, multiplier: multiplier)
}
}
然后您可以执行以下操作而无需强制转换:
for index in tableView.indexPathsForSelectedRows! {
wordLists.append(lists[index.row].copy())
}