使不可变函数参数可变
Making immutable function parameter mutable
我有一个接受数组的方法,在该方法中我想将一些对象附加到该数组。由于函数的 Swifts 参数是 immutable 我无法这样做。保持对该数组的相同引用至关重要,因为该数组将在 table 视图中用于显示数据。我的代码如下:
class func loadData(tableView: UITableView, results: [LocationInfo]){
print("\n Data fetch started \n")
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
for item in snapshot.children{
let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
results.append(locationInfo) // ERROR IS WITH THIS
}
DispatchQueue.main.async {
print("\n data fetch completed \n ")
tableView.reloadData()
print("After on completion method \(results.count)")
}
})
}
如何在保持相同引用的同时向此数组追加数据。
您可以通过将该数组声明为 属性(并删除函数的 class
修饰符)来使该数组对所有函数可用,或者您可以将函数的参数定义为 输入输出参数。通过在参数类型之前添加 inout
关键字,您可以通过保持对传递数组的引用来使参数可变。
尽管如此,我还是建议您将数组变成 属性 – 仅仅是因为它更容易,而且在我看来,更易于维护。
It is vital that I maintain the same reference to that array
那个愿望是不连贯的。考虑:locationSummary.observingSingleEvent
接受一个将 异步执行 的函数,也就是说,在某个 未知的未来时间 。但这正是您要通过 "same reference" 更改此数组的地方。说你会在某个未知的未来时间回来,并保持对某个持久变量的引用,然后突然改变它,这是疯狂的。
因此,这个[Location]
不能成为loadData
的参数。
我还建议问问自己为什么这需要是一个 class 函数。这意味着没有实例,所以无论如何都没有有意义的地方来存储持久变量!
如果这是一个普通的实例方法(即删除 class
),那么问题就很容易解决了:让你的 [Location]
成为一个实例 属性,现在你可以从您的异步函数中引用它。注意 (1) 仅在主线程上获取和设置它,以及 (2) 不要因意外保留 self
(你会想说 [weak self] in
)而陷入保留循环。
第一点:您不能 "maintain the same reference to that array" 因为那不是对数组的引用。它是一个临时值,只存在于方法结束之前。
我看到你有 table 观点。为了让 LocationInfo 对象显示在 table 视图中,您需要将 results
分配(即复制)到一个参数中,然后您可以使用该参数填充 table 视图。像这样简单的东西可能会起作用...这取决于您的其余代码的样子。
var tableViewData: [LocationInfo] = []
// note, this isn't a class func anymore.
func loadData(results: [LocationInfo]){
print("\n Data fetch started \n")
tableViewData = results
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
for item in snapshot.children{
let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
tableViewData.append(locationInfo)
}
DispatchQueue.main.async {
print("\n data fetch completed \n ")
self.tableView.reloadData()
print("After on completion method \(results.count)")
}
})
}
我有一个接受数组的方法,在该方法中我想将一些对象附加到该数组。由于函数的 Swifts 参数是 immutable 我无法这样做。保持对该数组的相同引用至关重要,因为该数组将在 table 视图中用于显示数据。我的代码如下:
class func loadData(tableView: UITableView, results: [LocationInfo]){
print("\n Data fetch started \n")
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
for item in snapshot.children{
let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
results.append(locationInfo) // ERROR IS WITH THIS
}
DispatchQueue.main.async {
print("\n data fetch completed \n ")
tableView.reloadData()
print("After on completion method \(results.count)")
}
})
}
如何在保持相同引用的同时向此数组追加数据。
您可以通过将该数组声明为 属性(并删除函数的 class
修饰符)来使该数组对所有函数可用,或者您可以将函数的参数定义为 输入输出参数。通过在参数类型之前添加 inout
关键字,您可以通过保持对传递数组的引用来使参数可变。
尽管如此,我还是建议您将数组变成 属性 – 仅仅是因为它更容易,而且在我看来,更易于维护。
It is vital that I maintain the same reference to that array
那个愿望是不连贯的。考虑:locationSummary.observingSingleEvent
接受一个将 异步执行 的函数,也就是说,在某个 未知的未来时间 。但这正是您要通过 "same reference" 更改此数组的地方。说你会在某个未知的未来时间回来,并保持对某个持久变量的引用,然后突然改变它,这是疯狂的。
因此,这个[Location]
不能成为loadData
的参数。
我还建议问问自己为什么这需要是一个 class 函数。这意味着没有实例,所以无论如何都没有有意义的地方来存储持久变量!
如果这是一个普通的实例方法(即删除 class
),那么问题就很容易解决了:让你的 [Location]
成为一个实例 属性,现在你可以从您的异步函数中引用它。注意 (1) 仅在主线程上获取和设置它,以及 (2) 不要因意外保留 self
(你会想说 [weak self] in
)而陷入保留循环。
第一点:您不能 "maintain the same reference to that array" 因为那不是对数组的引用。它是一个临时值,只存在于方法结束之前。
我看到你有 table 观点。为了让 LocationInfo 对象显示在 table 视图中,您需要将 results
分配(即复制)到一个参数中,然后您可以使用该参数填充 table 视图。像这样简单的东西可能会起作用...这取决于您的其余代码的样子。
var tableViewData: [LocationInfo] = []
// note, this isn't a class func anymore.
func loadData(results: [LocationInfo]){
print("\n Data fetch started \n")
tableViewData = results
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
for item in snapshot.children{
let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
tableViewData.append(locationInfo)
}
DispatchQueue.main.async {
print("\n data fetch completed \n ")
self.tableView.reloadData()
print("After on completion method \(results.count)")
}
})
}