使不可变函数参数可变

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)")

        }
    })
}